-
Notifications
You must be signed in to change notification settings - Fork 115
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
Cargo Stylus Factory #240
base: main
Are you sure you want to change the base?
Cargo Stylus Factory #240
Conversation
interface IArbWasm { | ||
function activateProgram( | ||
address program | ||
) external payable returns (uint16 version, uint256 dataFee); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should import from ./src/precompiles/ArbWasm.sol
// Function to deploy and init a new contract | ||
// NOTE: This function should only be invoked if | ||
// ArbWasm's codehashVersion(bytes32 codehash) method returns the | ||
// current stylusVersion(), verify this locally before invoking | ||
function deployInit( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of having a separate method, we can just conditional activate based on the result of codehashVersion
in the other method
can also conditional on if the activation cost provided is 0
// Initialize the contract | ||
initializeContract(newContractAddress, _constructorCalldata, msg.value); | ||
|
||
return newContractAddress; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
excess value not refunded (some constructor might refund callvalue)
) external payable returns (uint16 version, uint256 dataFee); | ||
} | ||
|
||
contract CargoStylusFactory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing a payable receive function to receive refund excess fund provided for activation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
specifically, I mean if dataFee < _activationValue
in
(, uint256 dataFee) = IArbWasm(ARB_WASM).activateProgram{value: _activationValue}(
_contract
);
I am not sure if that refund involves evm call tho
function deployContract(bytes memory _bytecode) internal returns (address) { | ||
address newContractAddress; | ||
|
||
assembly { | ||
newContractAddress := create(0, add(_bytecode, 0x20), mload(_bytecode)) | ||
} | ||
|
||
if (newContractAddress == address(0)) { | ||
revert ContractDeploymentError(_bytecode); | ||
} | ||
|
||
emit ContractDeployed(newContractAddress, msg.sender); | ||
|
||
return newContractAddress; | ||
} | ||
|
||
// Internal function to activate a Stylus contract | ||
function activateContract( | ||
address _contract, | ||
uint256 _activationValue | ||
) internal returns (uint256) { | ||
(, uint256 dataFee) = IArbWasm(ARB_WASM).activateProgram{value: _activationValue}( | ||
_contract | ||
); | ||
|
||
emit ContractActivated(_contract); | ||
|
||
return dataFee; | ||
} | ||
|
||
// Internal function to initialize a Stylus contract by | ||
// invoking its constructor | ||
function initializeContract( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we were to consolidate the 2 public function, we might as well inline these instead of making internal functions
initializeContract(newContractAddress, _constructorCalldata, _constructorValue); | ||
|
||
refundExcessValue(activationFee, _constructorValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this ignore any refund from the constructor call (if any), I think we can wrap a balance check before and after the call to constructor to know the net amount spent in the constructor and do refund appropriately
there is also an additional edge case where the constructor cost is negative (if it somehow received more fund from the constructor)
while there were some comment regarding constructor refund, maybe we can assume it will never happen like other CREATE2 factories |
_contract | ||
); | ||
|
||
emit ContractActivated(_contract); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm getting this error if the program was previously activated:
(code: 3, message: execution reverted: error ProgramUpToDate(), data: Some(String("0xcc944bf2")))
function activateContract( | ||
address _contract, | ||
uint256 _activationValue | ||
) internal returns (uint256) { | ||
(, uint256 dataFee) = IArbWasm(ARB_WASM).activateProgram{value: _activationValue}( | ||
_contract | ||
); | ||
|
||
emit ContractActivated(_contract); | ||
|
||
return dataFee; | ||
} |
Check warning
Code scanning / Slither
Unused return Medium
Draft for a Stylus factory contract that may be used by the
cargo stylus
CLI tool to deploy, activate, and run an arbitrary constructor in a single transaction.In Stylus/WASM context we are unable to run Rust or WASM code during the deployment step. There is also a need to activate WASM programs, which is currently abstracted from users via the
cargo stylus
tool. Users can currently define in their Rust code an "init" method but it must be called after activation and there is a need to gate the function manually to a specific deployer address as well as add arbitrary state variables to gate other methods from being invoked before the contract is initialized.This contract enables a better developer experience. The intention is to deterministically deploy this contract using create2 on Arbitrum chains so that Cargo Stylus can use it to deploy. The Stylus SDK will add a future
#[constructor]
proc macro that will gate a defined method to being invoked by this contract alone during the deployment transaction.