Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Proposed] ACP-99: Implement using composition - ValidatorManager as single entry point #668

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

cam-schultz
Copy link
Contributor

@cam-schultz cam-schultz commented Dec 3, 2024

Why this should be merged

Experimental implementation of ACP-99 using composition. Concrete contracts implement either IACP99SecurityModule or IACP99ValidatorManager.

Notably, the contract sizes decrease significantly. ERC20TokenStakingManager goes from right at the 24kB size limit down to 14.6kB.

This is not functional as-is, and is meant to demonstrate the necessary refactoring to implement ACP-99 using composition

How this works

classDiagram
class IACP99SecurityModule {
    handleInitializeValidatorRegistration()
    handleCompleteValidatorRegistration()
    handleInitializeEndValidation()
    handleCompleteEndValidation()
    handleInitializeValidatorWeightChange()
    handleCompleteValidatorWeightChange()
}
<<interface>> IACP99SecurityModule

class IACP99ValidatorManager {
    initializeValidatorSet()
    initializeValidatorRegistration()
    completeValidatorRegistration()
    initializeEndValidation()
    completeEndValidation()
    initializeValidatorWeightChange()
    completeValidatorWeightChange()
}

class PoSValidatorManager
<<abstract>> PoSValidatorManager

class ERC20TokenStakingManager
class NativeTokenStakingManager
class PoAValidatorManager
class ACP99ValidatorManager
class ValidatorManager
<<abstract>> ValidatorManager


ACP99ValidatorManager *-- IACP99SecurityModule


ValidatorManager <|-- ACP99ValidatorManager
IACP99ValidatorManager <|-- ACP99ValidatorManager

IACP99SecurityModule <|-- PoSValidatorManager
PoSValidatorManager <|-- ERC20TokenStakingManager
PoSValidatorManager <|-- NativeTokenStakingManager
IACP99SecurityModule <|-- PoAValidatorManager
Loading

This implementation deviates slightly from the ACP-99 spec as written in that the ValidatorManager is the only contract that the end user interacts with. To achieve this, the handle* method signatures must be generic enough to cover all possible SecurityModule use cases, notably PoA vs PoS. This results in a greater-than-minimal IACP99SecurityModule interface, where some implementations won't use certain arguments (for example PoA applications won't need payable methods, but native token staking applications will).

How this was tested

How is this documented

@richardpringle
Copy link
Contributor

Notably, the contract sizes decrease significantly. ERC20TokenStakingManager goes from right at the 24kB size limit down to 14.6kB.

I'm curious to know how much this affects gas costs, that would be one of the major advantages of keeping everything in a single contract, right?

abstract contract ACP99ValidatorManager is IACP99ValidatorManager, ValidatorManager {
IACP99SecurityModule public securityModule;

// TODO: calling this should be restricted to...who?
Copy link
Contributor

Choose a reason for hiding this comment

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

😜

Suggested change
// TODO: calling this should be restricted to...who?
// TODO: calling this should be restricted to...whom?

@cam-schultz
Copy link
Contributor Author

I'm curious to know how much this affects gas costs, that would be one of the major advantages of keeping everything in a single contract, right?

We won't know until we get unit tests working, but in theory the only added cost should be the external call to the security module. If we're not transferring ETH, and assuming the address is "warm" (it should be - every interaction will call the same security module), then gas is on the order of hundreds https://github.com/wolflo/evm-opcodes/blob/main/gas.md#aa-1-call

Copy link
Contributor

@richardpringle richardpringle left a comment

Choose a reason for hiding this comment

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

What's the key difference here, that the security module is a property of the validator-manager instead of the validator-manager implementing the security module interface?

// TODO: calling this should be restricted to...who?
function setSecurityModule(IACP99SecurityModule _securityModule) external {
securityModule = _securityModule;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the security module itself control its own upgrades? If not, should there be a SecurityUpdateModule?

bytes calldata args
) external returns (bytes32){
bytes32 validationID = _initializeValidatorRegistration(input, weight);
securityModule.handleInitializeValidatorRegistration(validationID, weight, args);
Copy link
Contributor

Choose a reason for hiding this comment

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

I definitely need to go through the ACP again, but I would expect the security module to do some form of validation on the inputs before calling the _initializeValidatorRegistration. Or does it not matter since the security module will just revert anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a little tricky to reverse the order in our current implementation since the security module needs the validationID, which is provided by the manager contract. It will revert if the security module's checks fail, regardless of the ordering. We should definitely keep in mind patterns such as checks-effects-interactions if/when we decide to move forward on this implementation.

@cam-schultz cam-schultz changed the title ACP-99: Implement using composition ACP-99: Implement using composition - ValidatorManager as single entry point Dec 6, 2024
@cam-schultz cam-schultz changed the title ACP-99: Implement using composition - ValidatorManager as single entry point [Proposed] ACP-99: Implement using composition - ValidatorManager as single entry point Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Backlog 🗄️
Development

Successfully merging this pull request may close these issues.

2 participants