diff --git a/examples/nft/contracts/Connected.sol b/examples/nft/contracts/Connected.sol index 482b815..9c19544 100644 --- a/examples/nft/contracts/Connected.sol +++ b/examples/nft/contracts/Connected.sol @@ -115,14 +115,14 @@ contract Connected is address receiver, uint256 tokenId, string memory uri, - uint256 amount, + uint256 gasAmount, address sender ) = abi.decode(message, (address, uint256, string, uint256, address)); _safeMint(receiver, tokenId); _setTokenURI(tokenId, uri); - if (amount > 0) { - (bool success, ) = sender.call{value: amount}(""); + if (gasAmount > 0) { + (bool success, ) = sender.call{value: gasAmount}(""); if (!success) revert GasTokenTransferFailed(); } emit TokenTransferReceived(receiver, tokenId, uri); diff --git a/examples/nft/contracts/Universal.sol b/examples/nft/contracts/Universal.sol index 07faddb..3aee92e 100644 --- a/examples/nft/contracts/Universal.sol +++ b/examples/nft/contracts/Universal.sol @@ -83,7 +83,13 @@ contract Universal is !IZRC20(destination).transferFrom(msg.sender, address(this), gasFee) ) revert TransferFailed(); IZRC20(destination).approve(address(gateway), gasFee); - bytes memory message = abi.encode(receiver, tokenId, uri, 0); + bytes memory message = abi.encode( + receiver, + tokenId, + uri, + 0, + msg.sender + ); CallOptions memory callOptions = CallOptions(gasLimit, false); @@ -125,7 +131,6 @@ contract Universal is uint256 amount, bytes calldata message ) external override onlyGateway { - revert("Method not implemented"); if (context.sender != counterparty[zrc20]) revert Unauthorized(); ( @@ -162,13 +167,8 @@ contract Universal is CallOptions(gasLimit, false), RevertOptions(address(0), false, address(0), "", 0) ); - emit TokenTransferToDestination( - receiver, - destination, - tokenId, - uri - ); } + emit TokenTransferToDestination(receiver, destination, tokenId, uri); } function onRevert(RevertContext calldata context) external onlyGateway { diff --git a/examples/token/contracts/Connected.sol b/examples/token/contracts/Connected.sol index 1c65054..95f2cb3 100644 --- a/examples/token/contracts/Connected.sol +++ b/examples/token/contracts/Connected.sol @@ -15,6 +15,7 @@ contract Connected is ERC20, Ownable2Step, Events { error InvalidAddress(); error Unauthorized(); error InvalidGasLimit(); + error GasTokenTransferFailed(); modifier onlyGateway() { if (msg.sender != address(gateway)) revert Unauthorized(); @@ -51,7 +52,12 @@ contract Connected is ERC20, Ownable2Step, Events { if (receiver == address(0)) revert InvalidAddress(); _burn(msg.sender, amount); - bytes memory message = abi.encode(destination, receiver, amount); + bytes memory message = abi.encode( + destination, + receiver, + amount, + msg.sender + ); if (destination == address(0)) { gateway.call( counterparty, @@ -66,7 +72,7 @@ contract Connected is ERC20, Ownable2Step, Events { address(this), true, address(0), - abi.encode(receiver, amount), + abi.encode(amount, msg.sender), gasLimit ) ); @@ -80,22 +86,28 @@ contract Connected is ERC20, Ownable2Step, Events { bytes calldata message ) external payable onlyGateway returns (bytes4) { if (context.sender != counterparty) revert Unauthorized(); - (address receiver, uint256 amount) = abi.decode( - message, - (address, uint256) - ); + ( + address receiver, + uint256 amount, + uint256 gasAmount, + address sender + ) = abi.decode(message, (address, uint256, uint256, address)); _mint(receiver, amount); + if (gasAmount > 0) { + (bool success, ) = sender.call{value: amount}(""); + if (!success) revert GasTokenTransferFailed(); + } emit TokenTransferReceived(receiver, amount); return ""; } function onRevert(RevertContext calldata context) external onlyGateway { - (address sender, uint256 amount) = abi.decode( + (uint256 amount, address receiver) = abi.decode( context.revertMessage, - (address, uint256) + (uint256, address) ); - _mint(sender, amount); - emit TokenTransferReverted(sender, amount); + _mint(receiver, amount); + emit TokenTransferReverted(receiver, amount); } receive() external payable {} diff --git a/examples/token/contracts/Universal.sol b/examples/token/contracts/Universal.sol index 4d940fb..07ad092 100644 --- a/examples/token/contracts/Universal.sol +++ b/examples/token/contracts/Universal.sol @@ -69,7 +69,7 @@ contract Universal is ERC20, Ownable2Step, UniversalContract, Events { !IZRC20(destination).transferFrom(msg.sender, address(this), gasFee) ) revert TransferFailed(); IZRC20(destination).approve(address(gateway), gasFee); - bytes memory message = abi.encode(receiver, amount); + bytes memory message = abi.encode(receiver, amount, 0, msg.sender); CallOptions memory callOptions = CallOptions(gasLimit, false); @@ -103,26 +103,31 @@ contract Universal is ERC20, Ownable2Step, UniversalContract, Events { ) external override onlyGateway { if (keccak256(context.origin) != keccak256(counterparty[zrc20])) revert Unauthorized(); - (address destination, address receiver, uint256 tokenAmount) = abi - .decode(message, (address, address, uint256)); + ( + address destination, + address receiver, + uint256 tokenAmount, + address sender + ) = abi.decode(message, (address, address, uint256, address)); if (destination == address(0)) { _mint(receiver, tokenAmount); } else { (, uint256 gasFee) = IZRC20(destination).withdrawGasFeeWithGasLimit( gasLimit ); - SwapHelperLib.swapExactTokensForTokens( + uint256 out = SwapHelperLib.swapExactTokensForTokens( uniswapRouter, zrc20, amount, destination, 0 ); - IZRC20(destination).approve(address(gateway), gasFee); - gateway.call( - counterparty[destination], + IZRC20(destination).approve(address(gateway), out); + gateway.withdrawAndCall( + abi.encodePacked(counterparty[destination]), + out - gasFee, destination, - abi.encode(receiver, tokenAmount), + abi.encode(receiver, tokenAmount, out - gasFee, sender), CallOptions(gasLimit, false), RevertOptions(address(0), false, address(0), "", 0) );