-
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.13; | ||
|
||
interface IArbWasm { | ||
function activateProgram( | ||
address program | ||
) external payable returns (uint16 version, uint256 dataFee); | ||
} | ||
|
||
contract CargoStylusFactory { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. specifically, I mean if
I am not sure if that refund involves evm call tho |
||
// Constants | ||
address constant ARB_WASM = 0x0000000000000000000000000000000000000071; | ||
|
||
// Events | ||
event ContractDeployed(address indexed deployedContract, address indexed deployer); | ||
event ContractActivated(address indexed activatedContract); | ||
event ContractInitialized(address indexed initializedContract); | ||
|
||
// Errors | ||
error ContractDeploymentError(bytes bytecode); | ||
error ContractInitializationError(address newContract); | ||
error RefundExcessValueError(uint256 excessValue); | ||
error ExecutionFailed(address target, bytes data); | ||
|
||
// Deploys, activate and inits a new contract | ||
function deployActivateInit( | ||
bytes calldata _bytecode, | ||
bytes calldata _constructorCalldata, | ||
uint256 _constructorValue | ||
) public payable returns (address) { | ||
uint256 activationValue = msg.value - _constructorValue; | ||
|
||
// Deploy the contract | ||
address newContractAddress = deployContract(_bytecode); | ||
|
||
// Activate the contract | ||
uint256 activationFee = activateContract(newContractAddress, activationValue); | ||
|
||
// Initialize the contract | ||
initializeContract(newContractAddress, _constructorCalldata, _constructorValue); | ||
|
||
refundExcessValue(activationFee, _constructorValue); | ||
Comment on lines
+40
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) |
||
|
||
return newContractAddress; | ||
} | ||
|
||
// 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( | ||
Comment on lines
+47
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
bytes calldata _bytecode, | ||
bytes calldata _constructorCalldata | ||
) public payable returns (address) { | ||
// Deploy the contract | ||
address newContractAddress = deployContract(_bytecode); | ||
|
||
// Initialize the contract | ||
initializeContract(newContractAddress, _constructorCalldata, msg.value); | ||
|
||
return newContractAddress; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. excess value not refunded (some constructor might refund callvalue) |
||
} | ||
|
||
// Computes amount to refund and sends it to msg.sender | ||
function refundExcessValue(uint256 _activationFee, uint256 _constructorValue) internal { | ||
// Calculate value to forward to constructor | ||
uint256 excessValue = msg.value - _activationFee - _constructorValue; | ||
|
||
// Refund excess value | ||
(bool sent, ) = payable(msg.sender).call{value: excessValue}(""); | ||
|
||
if (!sent) { | ||
revert RefundExcessValueError(excessValue); | ||
} | ||
} | ||
|
||
// Internal function to deploy a new contract | ||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm getting this error if the program was previously activated:
|
||
|
||
return dataFee; | ||
} | ||
Comment on lines
+95
to
+106
Check warning Code scanning / Slither Unused return Medium |
||
|
||
// Internal function to initialize a Stylus contract by | ||
// invoking its constructor | ||
function initializeContract( | ||
Comment on lines
+78
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
address _contract, | ||
bytes calldata _constructorCalldata, | ||
uint256 _constructorValue | ||
) internal { | ||
(bool success, ) = address(_contract).call{value: _constructorValue}(_constructorCalldata); | ||
|
||
if (!success) { | ||
revert ContractInitializationError(_contract); | ||
} | ||
|
||
emit ContractInitialized(_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.
should import from
./src/precompiles/ArbWasm.sol