Skip to content

Commit f5c9cd9

Browse files
committed
Call Contract with value
1 parent 10f8550 commit f5c9cd9

File tree

6 files changed

+71
-5
lines changed

6 files changed

+71
-5
lines changed

contracts/src/AgentExecutor.sol

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ contract AgentExecutor {
2828
_transferToken(token, recipient, amount);
2929
}
3030

31-
function callContract(address target, bytes memory data) external {
32-
bool success = Call.safeCall(target, data);
31+
function callContract(address target, bytes memory data, uint256 value) external {
32+
bool success = Call.safeCall(target, data, value);
3333
if (!success) {
3434
revert();
3535
}

contracts/src/utils/Call.sol

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ library Call {
3333
* @param target Address to call
3434
* @param data Calldata to pass to the call
3535
*/
36-
function safeCall(address target, bytes memory data) internal returns (bool) {
36+
function safeCall(address target, bytes memory data, uint256 value) internal returns (bool) {
3737
bool success;
3838
assembly {
3939
success :=
4040
call(
4141
gas(), // gas
4242
target, // recipient
43-
0, // ether value
43+
value, // ether value
4444
add(data, 0x20), // inloc
4545
mload(data), // inlen
4646
0, // outloc

contracts/src/v2/Handlers.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ library HandlersV2 {
8888
CallContractParams memory params = abi.decode(data, (CallContractParams));
8989
address agent = Functions.ensureAgent(origin);
9090
bytes memory call =
91-
abi.encodeCall(AgentExecutor.callContract, (params.target, params.data));
91+
abi.encodeCall(AgentExecutor.callContract, (params.target, params.data, params.value));
9292
Functions.invokeOnAgent(agent, executor, call);
9393
}
9494
}

contracts/src/v2/Types.sol

+2
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,6 @@ struct CallContractParams {
9494
address target;
9595
// Call data
9696
bytes data;
97+
// Ether value
98+
uint256 value;
9799
}

contracts/test/GatewayV2.t.sol

+41
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ import {
6262
import {WETH9} from "canonical-weth/WETH9.sol";
6363
import {UD60x18, ud60x18, convert} from "prb/math/src/UD60x18.sol";
6464

65+
import {HelloWorld} from "./mocks/HelloWorld.sol";
66+
6567
contract GatewayV2Test is Test {
6668
// Emitted when token minted/burnt/transfered
6769
event Transfer(address indexed from, address indexed to, uint256 value);
@@ -86,6 +88,10 @@ contract GatewayV2Test is Test {
8688
// tokenID for DOT
8789
bytes32 public dotTokenID;
8890

91+
HelloWorld public helloWorld;
92+
93+
event SaidHello(string indexed message);
94+
8995
function setUp() public {
9096
token = new WETH9();
9197
AgentExecutor executor = new AgentExecutor();
@@ -132,6 +138,8 @@ contract GatewayV2Test is Test {
132138
token.deposit{value: 500}();
133139

134140
dotTokenID = bytes32(uint256(1));
141+
142+
helloWorld = new HelloWorld();
135143
}
136144

137145
function recipientAddress32() internal pure returns (MultiAddress memory) {
@@ -172,6 +180,21 @@ contract GatewayV2Test is Test {
172180
return commands;
173181
}
174182

183+
function makeCallContractCommand(uint256 value) public view returns (CommandV2[] memory) {
184+
bytes memory data = abi.encodeWithSignature("sayHello(string)", "World");
185+
CallContractParams memory params = CallContractParams({
186+
target: address(helloWorld),
187+
data: data,
188+
value: value
189+
});
190+
bytes memory payload = abi.encode(params);
191+
192+
CommandV2[] memory commands = new CommandV2[](1);
193+
commands[0] =
194+
CommandV2({kind: CommandKind.CallContract, gas: 500_000, payload: payload});
195+
return commands;
196+
}
197+
175198
/**
176199
* Message Verification
177200
*/
@@ -289,4 +312,22 @@ contract GatewayV2Test is Test {
289312
message, proof, makeMockProof(), relayerRewardAddress
290313
);
291314
}
315+
316+
function testAgentCallContractSuccess() public {
317+
vm.expectEmit(true, false, false, true);
318+
emit IGatewayV2.InboundMessageDispatched(1, true, relayerRewardAddress);
319+
320+
vm.deal(assetHubAgent, 1 ether);
321+
hoax(relayer, 1 ether);
322+
IGatewayV2(address(gateway)).v2_submit(
323+
InboundMessageV2({
324+
origin: Constants.ASSET_HUB_AGENT_ID,
325+
nonce: 1,
326+
commands: makeCallContractCommand(0.1 ether)
327+
}),
328+
proof,
329+
makeMockProof(),
330+
relayerRewardAddress
331+
);
332+
}
292333
}

contracts/test/mocks/HelloWorld.sol

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity 0.8.25;
3+
4+
contract HelloWorld {
5+
event SaidHello(string indexed message);
6+
7+
error Unauthorized();
8+
9+
function sayHello(string memory _text) payable public {
10+
string memory fullMessage = string(abi.encodePacked("Hello there, ", _text));
11+
emit SaidHello(fullMessage);
12+
}
13+
14+
function revertUnauthorized() public pure {
15+
revert Unauthorized();
16+
}
17+
18+
function retBomb() public pure returns (bytes memory) {
19+
assembly {
20+
return(1, 3000000)
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)