diff --git a/foundry.toml b/foundry.toml index d9ee226..c7b3561 100644 --- a/foundry.toml +++ b/foundry.toml @@ -47,7 +47,7 @@ sizes = false via_ir = false no_storage_caching = false no_rpc_rate_limit = false -bytecode_hash = "none" +bytecode_hash = "ipfs" cbor_metadata = true fs_permissions = [ diff --git a/src/ORMP.sol b/src/ORMP.sol index 5ba0cb6..863dcf6 100644 --- a/src/ORMP.sol +++ b/src/ORMP.sol @@ -127,6 +127,7 @@ contract ORMP is ReentrancyGuard, Channel { /// @return dispatchResult Result of the message dispatch. function recv(Message calldata message, bytes calldata proof) external + payable recvNonReentrant returns (bool dispatchResult) { @@ -140,7 +141,10 @@ contract ORMP is ReentrancyGuard, Channel { function _dispatch(Message memory message, bytes32 msgHash) private returns (bool dispatchResult) { // Deliver the message to user application contract address. (dispatchResult,) = message.to.excessivelySafeCall( - message.gasLimit, 0, abi.encodePacked(message.encoded, msgHash, message.fromChainId, message.from) + message.gasLimit, + msg.value, + 0, + abi.encodePacked(message.encoded, msgHash, message.fromChainId, message.from) ); } } diff --git a/src/security/ExcessivelySafeCall.sol b/src/security/ExcessivelySafeCall.sol index e1b8fbb..aa7bf0f 100644 --- a/src/security/ExcessivelySafeCall.sol +++ b/src/security/ExcessivelySafeCall.sol @@ -16,12 +16,13 @@ library ExcessivelySafeCall { /// to memory. /// @param _target The address to call /// @param _gas The amount of gas to forward to the remote contract + /// @param _value Value in wei to send to the account /// @param _maxCopy The maximum number of bytes of returndata to copy /// to memory. /// @param _calldata The data to send to the remote contract /// @return success and returndata, as `.call()`. Returndata is capped to /// `_maxCopy` bytes. - function excessivelySafeCall(address _target, uint256 _gas, uint16 _maxCopy, bytes memory _calldata) + function excessivelySafeCall(address _target, uint256 _gas, uint256 _value, uint16 _maxCopy, bytes memory _calldata) internal returns (bool, bytes memory) { @@ -38,7 +39,7 @@ library ExcessivelySafeCall { call( _gas, // gas _target, // recipient - 0, // ether value + _value, // ether value add(_calldata, 0x20), // inloc mload(_calldata), // inlen 0, // outloc diff --git a/test/security/ExcessivelySafeCall.t.sol b/test/security/ExcessivelySafeCall.t.sol index b0c0998..d4fe93d 100644 --- a/test/security/ExcessivelySafeCall.t.sol +++ b/test/security/ExcessivelySafeCall.t.sol @@ -35,7 +35,7 @@ contract ContractTest is DSTest { bool _success; bytes memory _ret; - (_success, _ret) = target.excessivelySafeCall(100_000, 0, abi.encodeWithSelector(CallTarget.one.selector)); + (_success, _ret) = target.excessivelySafeCall(100_000, 0, 0, abi.encodeWithSelector(CallTarget.one.selector)); assertEq(t.called(), 1); } @@ -55,13 +55,13 @@ contract ContractTest is DSTest { bytes memory _ret; (_success, _ret) = target.excessivelySafeCall( - 100_000, _maxCopy, abi.encodeWithSelector(CallTarget.retBytes.selector, uint256(_requested)) + 100_000, 0, _maxCopy, abi.encodeWithSelector(CallTarget.retBytes.selector, uint256(_requested)) ); assertTrue(_success); assertEq(_ret.length, _toCopy, "return copied wrong amount"); (_success, _ret) = target.excessivelySafeCall( - 100_000, _maxCopy, abi.encodeWithSelector(CallTarget.revBytes.selector, uint256(_requested)) + 100_000, 0, _maxCopy, abi.encodeWithSelector(CallTarget.revBytes.selector, uint256(_requested)) ); assertTrue(!_success); assertEq(_ret.length, _toCopy, "revert copied wrong amount"); @@ -90,12 +90,14 @@ contract ContractTest is DSTest { bool _success; bytes memory _ret; - (_success, _ret) = target.excessivelySafeCall(3_000_000, 32, abi.encodeWithSelector(CallTarget.badRet.selector)); + (_success, _ret) = + target.excessivelySafeCall(3_000_000, 0, 32, abi.encodeWithSelector(CallTarget.badRet.selector)); assertTrue(_success); assertEq(returnSize(), 1_000_000, "didn't return all"); assertEq(_ret.length, 32, "revert didn't truncate"); - (_success, _ret) = target.excessivelySafeCall(3_000_000, 32, abi.encodeWithSelector(CallTarget.badRev.selector)); + (_success, _ret) = + target.excessivelySafeCall(3_000_000, 0, 32, abi.encodeWithSelector(CallTarget.badRev.selector)); assertTrue(!_success); assertEq(returnSize(), 1_000_000, "didn't return all"); assertEq(_ret.length, 32, "revert didn't truncate"); diff --git a/test/user/Application.t.sol b/test/user/Application.t.sol index b5a4037..377b956 100644 --- a/test/user/Application.t.sol +++ b/test/user/Application.t.sol @@ -33,14 +33,14 @@ contract ApplicationTest is Test { function test_recv() public { (bool dispatchResult,) = address(ua).excessivelySafeCall( - gasleft(), 0, abi.encodePacked(ua.recv.selector, bytes32(uint256(1)), uint256(1), self) + gasleft(), 0, 0, abi.encodePacked(ua.recv.selector, bytes32(uint256(1)), uint256(1), self) ); assertEq(dispatchResult, true); } function testFail_recv() public { (bool dispatchResult,) = address(ua).excessivelySafeCall( - gasleft(), 0, abi.encodePacked(ua.recv.selector, bytes32(uint256(1)), uint256(1), address(1)) + gasleft(), 0, 0, abi.encodePacked(ua.recv.selector, bytes32(uint256(1)), uint256(1), address(1)) ); assertEq(dispatchResult, true); }