Skip to content

Feat/v3#40

Merged
DicksonWu654 merged 57 commits intosecurity-alliance:mainfrom
PatrickAlphaC:feat/v3
Jan 27, 2026
Merged

Feat/v3#40
DicksonWu654 merged 57 commits intosecurity-alliance:mainfrom
PatrickAlphaC:feat/v3

Conversation

@PatrickAlphaC
Copy link
Copy Markdown
Contributor

@PatrickAlphaC PatrickAlphaC commented Dec 31, 2025

work in progress to solve: #39

TODO:

  • Get final list of owner addresses and chains to deploy new contracts to

TODO (after deployment):

  • Update references to on-chain contracts after deployment in legal docs

@Robert-MacWha
Copy link
Copy Markdown
Contributor

Is there a reason for the libs to be copied instead of references for legacy? Might have just been a mistake when cloning?

@PatrickAlphaC
Copy link
Copy Markdown
Contributor Author

Is there a reason for the libs to be copied instead of references for legacy? Might have just been a mistake when cloning?

Fixed!

@Robert-MacWha
Copy link
Copy Markdown
Contributor

The constructor is clever. If we want to retain the same address, we can just include all the adopters and the invalid ones will be skipped. And if there was no deployed registry it'll skip over the entire block.

Would it be better to exclude the chain validation logic from the registry? Right now the registry serves dual responsibilities, and opens the door to needing a new registry (or at least deprecating the current one) if the interface for agreement verification changes too much.

I would tentatively suggest:

contract SafeHarborRegistry is IRegistry { // Remove Ownable since no onlyOwner methods 
    error SafeHarborRegistry__NoAgreement();
    error SafeHarborRegistry__ZeroAddress();
    
    mapping(address entity => address details) private agreements;
    
    event SafeHarborAdoption(address indexed adopter, address agreementAddress);
    event LegacyDataMigrated(address indexed legacyRegistry, uint256 migratedCount);
    
    constructor(address _legacyRegistry, address[] memory _adopters)
    function adoptSafeHarbor(address _agreementAddress) external
    function version() external pure returns (string memory)
    function getAgreement(address _adopter) external view returns (address)
}

contract AgreementFactory {
    address private constant REGISTRY_ADDRESS;
    address private constant CHAIN_VALIDATOR_ADDRESS;
    function create(AgreementDetails memory details, address owner) external returns (address agreementAddress);
}

Or, if we want the chain validator to be variable, either using the AgreementFactory as the proxy or by letting the owners of an Agreement change their CHAIN_VALIDATOR_ADDRESS. Unless there's a good reason for mutable validator addresses I'd make them constant, otherwise would vote to move it to the factory.

@PatrickAlphaC
Copy link
Copy Markdown
Contributor Author

exclude the chain validation logic from the registry?

I'm not sure I follow, right now the registry has a function that allows the registry owner to change the chain validation logic contract:

 function setChainValidator(address _newChainValidator) external onlyOwner {
        if (_newChainValidator == address(0)) {
            revert SafeHarborRegistry__ZeroAddress();
        }
        emit ChainValidatorSet(_newChainValidator);
        chainValidator = IChainValidator(_newChainValidator);
    }

We created ChainValidator.sol to do the chain validation logic.

@PatrickAlphaC PatrickAlphaC marked this pull request as ready for review December 31, 2025 21:32
@PatrickAlphaC
Copy link
Copy Markdown
Contributor Author

I think the final thing for us to do, would be the following.

In our HelperConfig.s.sol we have different configs for each chain:

function getMainnetConfig() public pure returns (NetworkConfig memory) {
        address[] memory adopters = new address[](5);
        adopters[0] = RHEO;
        adopters[1] = OPS_COVEFI_ETH;
        adopters[2] = AAVE;
        adopters[3] = IDLE_FINANCE;
        adopters[4] = ENS;
        return NetworkConfig({
            owner: SEAL_MAINNET_OWNER,
            legacyRegistry: DEFAULT_LEGACY_REGISTRY,
            createx: CREATEX_ADDRESS,
            adopters: adopters
        });
    }

I'd need someone to make a PR to go through each chain and add the correct config information. I think it might be easy enough to set the owner to be SEAL_MAINNET_OWNER. What do you think?

@Robert-MacWha
Copy link
Copy Markdown
Contributor

exclude the chain validation logic from the registry?

I'm not sure I follow, right now the registry has a function that allows the registry owner to change the chain validation logic contract:

 function setChainValidator(address _newChainValidator) external onlyOwner {
        if (_newChainValidator == address(0)) {
            revert SafeHarborRegistry__ZeroAddress();
        }
        emit ChainValidatorSet(_newChainValidator);
        chainValidator = IChainValidator(_newChainValidator);
    }

We created ChainValidator.sol to do the chain validation logic.

Was suggesting we could move that proxy logic into a different contract so the registry contract is single-responsibility and isn't ownable

Trying to minimize the chance we ever need to deploy a new registry.

@DicksonWu654
Copy link
Copy Markdown
Contributor

exclude the chain validation logic from the registry?

I'm not sure I follow, right now the registry has a function that allows the registry owner to change the chain validation logic contract:

 function setChainValidator(address _newChainValidator) external onlyOwner {
        if (_newChainValidator == address(0)) {
            revert SafeHarborRegistry__ZeroAddress();
        }
        emit ChainValidatorSet(_newChainValidator);
        chainValidator = IChainValidator(_newChainValidator);
    }

We created ChainValidator.sol to do the chain validation logic.

Was suggesting we could move that proxy logic into a different contract so the registry contract is single-responsibility and isn't ownable

Trying to minimize the chance we ever need to deploy a new registry.

I agree. Imo right now the Registry is just middle manning the isValidChain function... But we can go direct and just have the ChainValidator inside of the agreements instead. That would simplify the Registry even further to basically be a mapping lol + remove the ownableness of it

I'll include that in my PR

@DicksonWu654
Copy link
Copy Markdown
Contributor

exclude the chain validation logic from the registry?

I'm not sure I follow, right now the registry has a function that allows the registry owner to change the chain validation logic contract:

 function setChainValidator(address _newChainValidator) external onlyOwner {
        if (_newChainValidator == address(0)) {
            revert SafeHarborRegistry__ZeroAddress();
        }
        emit ChainValidatorSet(_newChainValidator);
        chainValidator = IChainValidator(_newChainValidator);
    }

We created ChainValidator.sol to do the chain validation logic.

Was suggesting we could move that proxy logic into a different contract so the registry contract is single-responsibility and isn't ownable
Trying to minimize the chance we ever need to deploy a new registry.

I agree. Imo right now the Registry is just middle manning the isValidChain function... But we can go direct and just have the ChainValidator inside of the agreements instead. That would simplify the Registry even further to basically be a mapping lol + remove the ownableness of it

I'll include that in my PR

I think the only security consideration here is: If we somehow fuck up the ownership of the ChainValidator, we are fucked and need the protocols to deploy a new one and register the new one instead. If you have the option to change it, you can have a backup inside of the ownership of the registry to save it.... But it's likely they're the same owner? Also prob unlikely scenario?

@DicksonWu654
Copy link
Copy Markdown
Contributor

Yooo btw your construcutor is hella clever. Smart as hell

DicksonWu654 and others added 17 commits January 10, 2026 17:05
…ment scope, creating ambiguous whitehat coverage

feat: add validation for empty account addresses in Agreement contract

- Introduced a new error for invalid account addresses.
- Implemented checks to ensure that account addresses are not empty during agreement creation and chain addition.
- Added unit tests to verify the behavior when empty account addresses are provided.
feat: add validation for contact details in Agreement contract

- Introduced a new error for invalid contact details.
- Implemented validation to ensure contact names and contact fields are not empty during agreement creation and when setting contact details.
- Added unit tests to verify behavior for various invalid contact scenarios.
…emory allocation panic and denial of service

Refactor AgreementFactory: Optimize assembly memory usage for salt generation

- Updated the assembly code to use a pointer for memory storage, improving efficiency in generating the final salt for agreement creation.
- Ensured that the memory pointer is updated correctly after usage to prevent potential memory issues.
feat: add validation to prevent removal of all accounts in Agreement contract

- Introduced a new error to handle attempts to remove all accounts from a chain.
- Implemented checks in the removeAccounts function to ensure at least one account remains.
- Added unit tests to verify the new behavior when attempting to remove all accounts.
…nputs

Refactor Agreement and ChainValidator contracts to use calldata for function parameters

- Updated function signatures in Agreement and ChainValidator contracts to use 'calldata' instead of 'memory' for string and array parameters, optimizing gas usage and improving efficiency.
- Functions affected include setProtocolName, setContactDetails, addChains, addAccounts in Agreement, and initialize in ChainValidator.
… in agreement scope, creating ambiguous whitehat coverage

feat: add validation for non-empty account addresses in Agreement contract

- Implemented checks to ensure that each account address provided in the addAccounts function is non-empty.
- Introduced a new error for invalid account addresses to handle cases where empty addresses are submitted.
- Added unit tests to verify that attempts to add accounts with empty addresses correctly revert the transaction.
Refactor loop initialization in Agreement, ChainValidator, and SafeHarborRegistry contracts

- Updated for-loops to initialize the loop variable without an explicit starting value, improving code readability.
- Ensured consistency across multiple functions in the Agreement and ChainValidator contracts, as well as in the SafeHarborRegistry contract.
Refactor Agreement contract: Optimize loop variable initialization

- Updated for-loops in the Agreement contract to store the length of arrays in a variable before iteration, enhancing code readability and performance.
- Ensured consistency in loop initialization across multiple functions within the contract.
…named returns

Refactor AgreementFactory: Remove redundant return statement in createAgreement function

- Eliminated the return statement in the createAgreement function as it was unnecessary, streamlining the code.
- This change enhances code clarity and maintains the function's intended behavior.
Refactor ChainValidator: Optimize loop variable usage in setValidChains and setInvalidChains functions

- Updated for-loops in the setValidChains and setInvalidChains functions to directly use the length of the input array, improving code clarity and reducing unnecessary variable declarations.
- This change enhances readability and maintains the intended functionality of the contract.
…ement and smart contracts

Everything except for Version

Refactor Agreement contract: Update struct definitions and terminology for clarity

- Revised the definitions of DAO Adoption Procedures, BountyTerms, and IdentityRequirements structs to enhance clarity and consistency.
- Changed references from 'AgreementDetailsV2' to 'AgreementDetails' and updated variable names for better understanding.
- Ensured that all instances of struct definitions are aligned with the latest terminology and specifications.
…not implemented in Chain struct

Refactor Agreement contract: Remove redundant signature reference and enhance clarity

- Eliminated the optional signature reference in the agreement section to streamline the document.
- Improved the overall clarity of the agreement by refining the language and structure of the contact details and bounty terms sections.
…nputs - Fixed back to memory for gas

Refactor Agreement contract: Change addChains function parameter from calldata to memory

- Updated the addChains function to accept the _chains parameter as memory instead of calldata, improving compatibility with internal function calls.
- This change enhances the flexibility of the function while maintaining its intended functionality.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wanted to check when this was created. I noticed it's not running - should it be, or if not can we remove it?

- Introduced the QUICKSWAP address for the Polygon network in the HelperConfig contract.
- Expanded the adopters array in the getPolygonConfig function to include QUICKSWAP, enhancing the network configuration.
…efinitions

- Updated the version number in the agreement document to v3.0.0.
- Revised struct definitions for DAO Adoption Procedures, BountyTerms, and ContactDetails for improved clarity and consistency.
- Changed references to specific contract addresses and updated terminology to align with the latest specifications.
…cument

- Fixed typographical errors in references to the Security Team and IdentityRequirements struct.
- Improved clarity in the language of the Conditions Precedent and Release by Protocol Community sections to ensure consistency and understanding.
@DicksonWu654 DicksonWu654 merged commit 22d6e85 into security-alliance:main Jan 27, 2026
2 checks passed
@DicksonWu654
Copy link
Copy Markdown
Contributor

Merged now - Thank you so so so much Patrick & Cyfrin ❤️

This was referenced Jan 27, 2026
Closed
@PatrickAlphaC
Copy link
Copy Markdown
Contributor Author

Beautiful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants