Skip to content

Commit

Permalink
feat: add msg.value for dst chain exec
Browse files Browse the repository at this point in the history
  • Loading branch information
sujithsomraaj committed Aug 28, 2023
1 parent 2e07a09 commit 1732dcd
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 25 deletions.
9 changes: 4 additions & 5 deletions src/MultiMessageReceiver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ contract MultiMessageReceiver is IMultiMessageReceiver, ExecutorAware, Initializ

/// stores the message if the amb is the first one delivering the message
if (prevStored.target == address(0)) {
msgReceived[msgId] = ExecutionData(_message.target, _message.callData, _message.nonce, _message.expiration);
msgReceived[msgId] = ExecutionData(
_message.target, _message.callData, _message.nativeValue, _message.nonce, _message.expiration
);
}

emit SingleBridgeMsgReceived(msgId, _bridgeName, _message.nonce, msg.sender);
Expand Down Expand Up @@ -166,10 +168,7 @@ contract MultiMessageReceiver is IMultiMessageReceiver, ExecutorAware, Initializ

/// @dev queues the action on timelock for execution
IGovernanceTimelock(governanceTimelock).scheduleTransaction(
_execData.target,
0,
/// NOTE: should we ever send native fees
_execData.callData
_execData.target, _execData.value, _execData.callData
);

emit MessageExecuted(msgId, _execData.target, _execData.nonce, _execData.callData);
Expand Down
21 changes: 15 additions & 6 deletions src/MultiMessageSender.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,22 +96,29 @@ contract MultiMessageSender {
/// @param _dstChainId is the destination chainId
/// @param _target is the target execution point on dst chain
/// @param _callData is the data to be sent to _target by low-level call(eg. address(_target).call(_callData))
function remoteCall(uint256 _dstChainId, address _target, bytes calldata _callData) external payable onlyCaller {
/// @param _nativeValue is the value to be sent to _target by low-level call (eg. address(_target).call{value: _nativeValue}(_callData))
function remoteCall(uint256 _dstChainId, address _target, bytes calldata _callData, uint256 _nativeValue)
external
payable
onlyCaller
{
address[] memory excludedAdapters;
_remoteCall(_dstChainId, _target, _callData, excludedAdapters);
_remoteCall(_dstChainId, _target, _callData, _nativeValue, excludedAdapters);
}

/// @param _dstChainId is the destination chainId
/// @param _target is the target execution point on dst chain
/// @param _callData is the data to be sent to _target by low-level call(eg. address(_target).call(_callData))
/// @param _nativeValue is the value to be sent to _target by low-level call (eg. address(_target).call{value: _nativeValue}(_callData))
/// @param _excludedAdapters are the sender adapters to be excluded from relaying the message
function remoteCall(
uint256 _dstChainId,
address _target,
bytes calldata _callData,
uint256 _nativeValue,
address[] calldata _excludedAdapters
) external payable onlyCaller {
_remoteCall(_dstChainId, _target, _callData, _excludedAdapters);
_remoteCall(_dstChainId, _target, _callData, _nativeValue, _excludedAdapters);
}

/// @notice Add bridge sender adapters
Expand Down Expand Up @@ -147,10 +154,11 @@ contract MultiMessageSender {
uint256 _dstChainId,
address _multiMessageReceiver,
address _target,
bytes calldata _callData
bytes calldata _callData,
uint256 _nativeValue
) public view returns (uint256 totalFee) {
MessageLibrary.Message memory message =
MessageLibrary.Message(block.chainid, _dstChainId, _target, nonce, _callData, 0);
MessageLibrary.Message(block.chainid, _dstChainId, _target, nonce, _callData, _nativeValue, 0);
bytes memory data;

/// @dev writes to memory for saving gas
Expand Down Expand Up @@ -183,6 +191,7 @@ contract MultiMessageSender {
uint256 _dstChainId,
address _target,
bytes calldata _callData,
uint256 _nativeValue,
address[] memory _excludedAdapters
) private {
LocalCallVars memory v;
Expand Down Expand Up @@ -240,7 +249,7 @@ contract MultiMessageSender {
v.msgExpiration = block.timestamp + gac.getMsgExpiryTime();

MessageLibrary.Message memory message =
MessageLibrary.Message(block.chainid, _dstChainId, _target, nonce, _callData, v.msgExpiration);
MessageLibrary.Message(block.chainid, _dstChainId, _target, nonce, _callData, _nativeValue, v.msgExpiration);

v.adapterSuccess = new bool[](v.adapterLength);

Expand Down
24 changes: 14 additions & 10 deletions src/controllers/GovernanceTimelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ contract GovernanceTimelock is IGovernanceTimelock {
uint256 public txCounter;
uint256 public delay = MINIMUM_DELAY;
uint256 public execPeriod = MINIMUM_EXECUTION_PERIOD;
address public admin; /// @dev the admin is the one allowed to schedule events
address public admin;
/// @dev the admin is the one allowed to schedule events

mapping(uint256 txId => ScheduledTransaction) public scheduledTransaction;

Expand Down Expand Up @@ -66,27 +67,23 @@ contract GovernanceTimelock is IGovernanceTimelock {
////////////////////////////////////////////////////////////////*/

/// @inheritdoc IGovernanceTimelock
function scheduleTransaction(address _target, uint256 _value, bytes memory _data)
external
override
onlyAdmin
{
function scheduleTransaction(address _target, uint256 _value, bytes memory _data) external override onlyAdmin {
if (_target == address(0)) {
revert Error.INVALID_TARGET();
}

/// increment tx counter
++txCounter;
uint256 eta = block.timestamp + delay;
uint256 expiry = eta + execPeriod;
uint256 expiry = eta + execPeriod;

scheduledTransaction[txCounter] = ScheduledTransaction(_target, _value, _data, eta, expiry, false);

emit TransactionScheduled(txCounter, _target, _value, _data, eta, expiry);
}

/// @inheritdoc IGovernanceTimelock
function executeTransaction(uint256 txId) external override {
function executeTransaction(uint256 txId) external payable override {
/// @dev validates the txId
if (txId == 0 || txId > txCounter) {
revert Error.INVALID_TX_ID();
Expand All @@ -105,10 +102,15 @@ contract GovernanceTimelock is IGovernanceTimelock {
}

/// @dev checks if tx within execution period
if(block.timestamp > transaction.expiry) {
if (block.timestamp > transaction.expiry) {
revert Error.TX_EXPIRED();
}

/// @dev checks native funding
if (msg.value != transaction.value) {
revert Error.TX_UNDERPAID();
}

transaction.isExecuted = true;

(bool status,) = transaction.target.call(transaction.data);
Expand All @@ -117,7 +119,9 @@ contract GovernanceTimelock is IGovernanceTimelock {
revert Error.EXECUTION_FAILS_ON_DST();
}

emit TransactionExecuted(txId, transaction.target, transaction.value, transaction.data, transaction.eta, transaction.expiry);
emit TransactionExecuted(
txId, transaction.target, transaction.value, transaction.data, transaction.eta, transaction.expiry
);
}

/// @inheritdoc IGovernanceTimelock
Expand Down
10 changes: 7 additions & 3 deletions src/interfaces/IGovernanceTimelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ interface IGovernanceTimelock {
/*/////////////////////////////////////////////////////////////////
EVENTS
////////////////////////////////////////////////////////////////*/
event TransactionScheduled(uint256 indexed txId, address target, uint256 value, bytes data, uint256 eta, uint256 expiry);
event TransactionExecuted(uint256 indexed txId, address target, uint256 value, bytes data, uint256 eta, uint256 expiry);
event TransactionScheduled(
uint256 indexed txId, address target, uint256 value, bytes data, uint256 eta, uint256 expiry
);
event TransactionExecuted(
uint256 indexed txId, address target, uint256 value, bytes data, uint256 eta, uint256 expiry
);

event ExecutionPeriodUpdated(uint256 oldPeriod, uint256 newPeriod);
event DelayUpdated(uint256 oldDelay, uint256 newDelay);
Expand All @@ -38,7 +42,7 @@ interface IGovernanceTimelock {

/// @notice Executes a previously scheduled transaction if it has reached its ETA.
/// @param _txId is the unqiue identifier of the scheduled transaction
function executeTransaction(uint256 _txId) external;
function executeTransaction(uint256 _txId) external payable;

/// @notice Updates the minimum delay for a transaction before it can be executed.
/// @dev This can only be invoked by through this timelock contract, thus requiring that an update go through the required time delay first.
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/IMultiMessageReceiver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface IMultiMessageReceiver {
struct ExecutionData {
address target;
bytes callData;
uint256 value;
uint256 nonce;
uint256 expiration;
}
Expand Down
3 changes: 3 additions & 0 deletions src/libraries/Error.sol
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ library Error {
/// @dev is thrown if tx id is already executed
error TX_ALREADY_EXECUTED();

/// @dev is thrown if msg.value is not enough
error TX_UNDERPAID();

/// @dev is thrown if timelock period is not over
error TX_TIMELOCKED();

Expand Down
3 changes: 3 additions & 0 deletions src/libraries/Message.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ library MessageLibrary {
/// @param nonce is an incrementing number held by MultiMessageSender to ensure msgId uniqueness
/// @param target is the contract to be called on dst chain
/// @param callData is the data to be sent to target by low-level call(eg. address(target).call(callData))
/// @param nativeValue is the native token value to be sent to target in the low-level call(eg. address(target).call{value: nativeValue}(callData))
/// @param expiration is the unix time when the message expires, zero means never expire
struct Message {
uint256 srcChainId;
uint256 dstChainId;
address target;
uint256 nonce;
bytes callData;
uint256 nativeValue;
uint256 expiration;
}

Expand All @@ -30,6 +32,7 @@ library MessageLibrary {
_message.nonce,
_message.target,
_message.callData,
_message.nativeValue,
_message.expiration
)
);
Expand Down
2 changes: 1 addition & 1 deletion test/success-tests/SimpleMMA.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ contract MMA is Setup {
/// send cross-chain message using MMA infra
vm.recordLogs();
MultiMessageSender(contractAddress[1][bytes("MMA_SENDER")]).remoteCall{value: 2 ether}(
137, address(target), abi.encode(MockUniswapReceiver.setValue.selector, "")
137, address(target), abi.encode(MockUniswapReceiver.setValue.selector, ""), 0
);

Vm.Log[] memory logs = vm.getRecordedLogs();
Expand Down

0 comments on commit 1732dcd

Please sign in to comment.