-
Notifications
You must be signed in to change notification settings - Fork 60
onlyGateway modifier #213
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
onlyGateway modifier #213
Changes from all commits
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 |
|---|---|---|
|
|
@@ -33,6 +33,11 @@ contract Universal is | |
|
|
||
| event CounterpartySet(address indexed zrc20, bytes indexed contractAddress); | ||
|
|
||
| modifier onlyGateway() { | ||
| require(msg.sender == address(gateway), "Caller is not the gateway"); | ||
| _; | ||
| } | ||
|
|
||
| constructor( | ||
| address payable gatewayAddress, | ||
| address initialOwner | ||
|
|
@@ -102,7 +107,7 @@ contract Universal is | |
| address zrc20, | ||
| uint256 amount, | ||
| bytes calldata message | ||
| ) external override { | ||
| ) external override onlyGateway { | ||
| if (keccak256(context.origin) != keccak256(counterparty[zrc20])) | ||
| revert("Unauthorized"); | ||
|
|
||
|
|
@@ -140,7 +145,7 @@ contract Universal is | |
| } | ||
| } | ||
|
|
||
| function onRevert(RevertContext calldata context) external { | ||
| function onRevert(RevertContext calldata context) external onlyGateway { | ||
|
Contributor
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. 🛠️ Refactor suggestion Add input validation for onRevert handler. While the Add input validation: function onRevert(RevertContext calldata context) external onlyGateway {
(uint256 tokenId, address sender, string memory uri) = abi.decode(
context.revertMessage,
(uint256, address, string)
);
+ require(sender != address(0), "Invalid sender address");
+ require(bytes(uri).length > 0, "Empty URI");
_safeMint(sender, tokenId);
_setTokenURI(tokenId, uri);
} |
||
| (uint256 tokenId, address sender, string memory uri) = abi.decode( | ||
| context.revertMessage, | ||
| (uint256, address, string) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,31 +45,31 @@ npx hardhat connected-set-counterparty --network localhost --contract "$CONTRACT | |
| npx hardhat universal-set-counterparty --network localhost --contract "$CONTRACT_ZETACHAIN" --counterparty "$CONTRACT_ETHEREUM" --zrc20 "$ZRC20_ETHEREUM" --json &>/dev/null | ||
| npx hardhat universal-set-counterparty --network localhost --contract "$CONTRACT_ZETACHAIN" --counterparty "$CONTRACT_BNB" --zrc20 "$ZRC20_BNB" --json &>/dev/null | ||
|
|
||
| nft_balance | ||
| npx hardhat localnet-check | ||
| nft_balance | ||
|
Contributor
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. 🛠️ Refactor suggestion Enhance visibility of NFT state transitions. While the current placement of Consider this pattern for operations: +# Before minting
+echo -e "\nInitial balances:"
+nft_balance
+
NFT_ID=$(npx hardhat mint --network localhost --json --contract "$CONTRACT_ZETACHAIN" --token-uri https://example.com/nft/metadata/1 | jq -r '.tokenId')
echo -e "\nMinted NFT with ID: $NFT_ID on ZetaChain."
npx hardhat localnet-check
+echo -e "\nBalances after minting:"
nft_balanceApply this pattern before and after each major operation (transfers) to provide clear visibility of state changes. Also applies to: 55-55, 61-61, 67-67, 73-73 |
||
|
|
||
| NFT_ID=$(npx hardhat mint --network localhost --json --contract "$CONTRACT_ZETACHAIN" --token-uri https://example.com/nft/metadata/1 | jq -r '.tokenId') | ||
| echo -e "\nMinted NFT with ID: $NFT_ID on ZetaChain." | ||
|
|
||
| nft_balance | ||
| npx hardhat localnet-check | ||
| nft_balance | ||
|
|
||
| echo -e "\nTransferring NFT: ZetaChain → Ethereum..." | ||
| npx hardhat transfer --network localhost --json --token-id "$NFT_ID" --from "$CONTRACT_ZETACHAIN" --to "$ZRC20_ETHEREUM" | ||
|
|
||
| nft_balance | ||
| npx hardhat localnet-check | ||
| nft_balance | ||
|
|
||
| echo -e "\nTransferring NFT: Ethereum → BNB..." | ||
| npx hardhat transfer --network localhost --json --token-id "$NFT_ID" --from "$CONTRACT_ETHEREUM" --to "$ZRC20_BNB" --gas-amount 0.1 | ||
|
|
||
| nft_balance | ||
| npx hardhat localnet-check | ||
| nft_balance | ||
|
|
||
| echo -e "\nTransferring NFT: BNB → ZetaChain..." | ||
| npx hardhat transfer --network localhost --json --token-id "$NFT_ID" --from "$CONTRACT_BNB" | ||
|
|
||
| nft_balance | ||
| npx hardhat localnet-check | ||
| nft_balance | ||
|
|
||
| npx hardhat localnet-stop | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,11 @@ contract Swap is UniversalContract { | |
| GatewayZEVM public gateway; | ||
| uint256 constant BITCOIN = 18332; | ||
|
|
||
| modifier onlyGateway() { | ||
| require(msg.sender == address(gateway), "Caller is not the gateway"); | ||
| _; | ||
| } | ||
|
|
||
| constructor(address systemContractAddress, address payable gatewayAddress) { | ||
| systemContract = SystemContract(systemContractAddress); | ||
| gateway = GatewayZEVM(gatewayAddress); | ||
|
|
@@ -31,7 +36,7 @@ contract Swap is UniversalContract { | |
| address zrc20, | ||
| uint256 amount, | ||
| bytes calldata message | ||
| ) external override { | ||
| ) external override onlyGateway { | ||
|
Contributor
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. 🛠️ Refactor suggestion Consider adding reentrancy protection. While the - ) external override onlyGateway {
+ ) external override onlyGateway nonReentrant {Add the ReentrancyGuard import and inheritance: import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract Swap is UniversalContract, ReentrancyGuard { |
||
| Params memory params = Params({target: address(0), to: bytes("")}); | ||
| if (context.chainID == BITCOIN) { | ||
| params.target = BytesHelperLib.bytesToAddress(message, 0); | ||
|
|
@@ -105,5 +110,7 @@ contract Swap is UniversalContract { | |
| ); | ||
| } | ||
|
|
||
| function onRevert(RevertContext calldata revertContext) external override {} | ||
| function onRevert( | ||
| RevertContext calldata revertContext | ||
| ) external override onlyGateway {} | ||
| } | ||
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.
💡 Codebase verification
🛠️ Refactor suggestion
Hardcoded gas limit needs to be replaced with state variable
The review comment is partially correct. After analyzing the contract:
gasLimitinitialized to 700000, but theonCallfunction uses the hardcoded value instead of this configurable variable._safeMintand_setTokenURI) occur before external callsonlyGatewaymodifier provides additional security by restricting accessSuggested improvements:
700000withgasLimitstate variable inonCallfunction:🔗 Analysis chain
Consider gas limit configuration and reentrancy protection.
While the
onlyGatewaymodifier addition enhances security, there are two considerations:gasLimitstate variable.Consider these improvements:
Let's verify the external call patterns:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 106
Script:
Length of output: 1445
Script:
Length of output: 6279