Skip to content

Commit

Permalink
Merge branch 'main' into unit-test-timelock
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominator008 committed Sep 12, 2023
2 parents 001ab9d + dc99b0f commit ff00c1b
Show file tree
Hide file tree
Showing 17 changed files with 595 additions and 136 deletions.
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
FOUNDRY_PROFILE=local
ETH_FORK_URL=
BSC_FORK_URL=
POLYGON_FORK_URL=
Expand Down
10 changes: 10 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,14 @@ optimizer = true
runs = 100
viaIR = true

[profile.local]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.19"

optimizer = false
runs = 100
viaIR = false

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
100 changes: 58 additions & 42 deletions src/MultiMessageReceiver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,27 +58,14 @@ contract MultiMessageReceiver is IMultiMessageReceiver, ExecutorAware, Initializ
////////////////////////////////////////////////////////////////*/

/// @notice sets the initial parameters
function initialize(address[] calldata _receiverAdapters, uint64 _quorum, address _governanceTimelock)
external
initializer
{
uint256 len = _receiverAdapters.length;

if (len == 0) {
revert Error.ZERO_RECEIVER_ADAPTER();
}

for (uint256 i; i < len;) {
if (_receiverAdapters[i] == address(0)) {
revert Error.ZERO_ADDRESS_INPUT();
}

_updateReceiverAdapter(_receiverAdapters[i], true);

unchecked {
++i;
}
}
function initialize(
address[] calldata _receiverAdapters,
bool[] calldata _operations,
uint64 _quorum,
address _governanceTimelock
) external initializer {
/// @dev adds the new receiver adapters before setting quorum and validations
_updateReceiverAdapters(_receiverAdapters, _operations);

if (_quorum > trustedExecutor.length || _quorum == 0) {
revert Error.INVALID_QUORUM_THRESHOLD();
Expand Down Expand Up @@ -180,35 +167,30 @@ contract MultiMessageReceiver is IMultiMessageReceiver, ExecutorAware, Initializ

/// @notice Update bridge receiver adapters.
/// @dev called by admin to update receiver bridge adapters on all other chains
function updateReceiverAdapter(address[] calldata _receiverAdapters, bool[] calldata _operations)
function updateReceiverAdapters(address[] calldata _receiverAdapters, bool[] calldata _operations)
external
onlyGovernanceTimelock
{
uint256 len = _receiverAdapters.length;

if (len != _operations.length) {
revert Error.ARRAY_LENGTH_MISMATCHED();
}

for (uint256 i; i < len;) {
_updateReceiverAdapter(_receiverAdapters[i], _operations[i]);
_updateReceiverAdapters(_receiverAdapters, _operations);
}

unchecked {
++i;
}
}
/// @notice Update bridge receiver adapters after quorum update
/// @dev called by admin to update receiver bridge adapters on all other chains
function updateQuorumAndReceiverAdapter(
uint64 _newQuorum,
address[] calldata _receiverAdapters,
bool[] calldata _operations
) external onlyGovernanceTimelock {
/// @dev updates quorum here
_updateQuorum(_newQuorum);

/// @dev updates receiver adapter here
_updateReceiverAdapters(_receiverAdapters, _operations);
}

/// @notice Update power quorum threshold of message execution.
function updateQuorum(uint64 _quorum) external onlyGovernanceTimelock {
/// NOTE: should check 2/3 ?
if (_quorum > trustedExecutor.length || _quorum == 0) {
revert Error.INVALID_QUORUM_THRESHOLD();
}
uint64 oldValue = quorum;

quorum = _quorum;
emit QuorumUpdated(oldValue, _quorum);
_updateQuorum(_quorum);
}

/*/////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -241,6 +223,40 @@ contract MultiMessageReceiver is IMultiMessageReceiver, ExecutorAware, Initializ
PRIVATE/INTERNAL FUNCTIONS
////////////////////////////////////////////////////////////////*/

function _updateQuorum(uint64 _quorum) internal {
if (_quorum > trustedExecutor.length || _quorum == 0) {
revert Error.INVALID_QUORUM_THRESHOLD();
}
uint64 oldValue = quorum;

quorum = _quorum;
emit QuorumUpdated(oldValue, _quorum);
}

function _updateReceiverAdapters(address[] memory _receiverAdapters, bool[] memory _operations) internal {
uint256 len = _receiverAdapters.length;

if (len == 0) {
revert Error.ZERO_RECEIVER_ADAPTER();
}

if (len != _operations.length) {
revert Error.ARRAY_LENGTH_MISMATCHED();
}

for (uint256 i; i < len;) {
if (_receiverAdapters[i] == address(0)) {
revert Error.ZERO_ADDRESS_INPUT();
}

_updateReceiverAdapter(_receiverAdapters[i], _operations[i]);

unchecked {
++i;
}
}
}

function _updateReceiverAdapter(address _receiverAdapter, bool _add) private {
if (_add) {
_addTrustedExecutor(_receiverAdapter);
Expand Down
46 changes: 34 additions & 12 deletions src/MultiMessageSender.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@ import "./libraries/Error.sol";
/// @title MultiMessageSender
/// @dev handles the routing of message from external sender to bridge adapters
contract MultiMessageSender {
/*///////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/
IGAC public immutable gac;

uint256 public constant MINIMUM_EXPIRATION = 2 days;
uint256 public constant MAXIMUM_EXPIRATION = 30 days;

/*/////////////////////////////////////////////////////////////////
STATE VARIABLES
////////////////////////////////////////////////////////////////*/
Expand All @@ -37,6 +43,7 @@ contract MultiMessageSender {
uint256 indexed dstChainId,
address indexed target,
bytes callData,
uint256 nativeValue,
uint256 expiration,
address[] senderAdapters,
bool[] adapterSuccess
Expand Down Expand Up @@ -69,6 +76,18 @@ contract MultiMessageSender {
_;
}

/// @dev validates the expiration provided by the user
modifier validateExpiration(uint256 _expiration) {
if (_expiration < MINIMUM_EXPIRATION) {
revert Error.INVALID_EXPIRATION_MIN();
}

if (_expiration > MAXIMUM_EXPIRATION) {
revert Error.INVALID_EXPIRATION_MAX();
}
_;
}

/*/////////////////////////////////////////////////////////////////
CONSTRUCTOR
////////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -97,28 +116,33 @@ contract MultiMessageSender {
/// @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))
function remoteCall(uint256 _dstChainId, address _target, bytes calldata _callData, uint256 _nativeValue)
external
payable
onlyCaller
{
/// @param _expiration refers to the number of days that a message remains valid before it is considered stale and can no longer be executed.
function remoteCall(
uint256 _dstChainId,
address _target,
bytes calldata _callData,
uint256 _nativeValue,
uint256 _expiration
) external payable onlyCaller {
address[] memory excludedAdapters;
_remoteCall(_dstChainId, _target, _callData, _nativeValue, excludedAdapters);
_remoteCall(_dstChainId, _target, _callData, _nativeValue, _expiration, 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
/// @param _expiration refers to the number of days that a message remains valid before it is considered stale and can no longer be executed.
function remoteCall(
uint256 _dstChainId,
address _target,
bytes calldata _callData,
uint256 _nativeValue,
uint256 _expiration,
address[] calldata _excludedAdapters
) external payable onlyCaller {
_remoteCall(_dstChainId, _target, _callData, _nativeValue, _excludedAdapters);
_remoteCall(_dstChainId, _target, _callData, _nativeValue, _expiration, _excludedAdapters);
}

/// @notice Add bridge sender adapters
Expand Down Expand Up @@ -182,7 +206,6 @@ contract MultiMessageSender {
struct LocalCallVars {
address[] adapters;
uint256 adapterLength;
uint256 msgExpiration;
bool[] adapterSuccess;
bytes32 msgId;
}
Expand All @@ -192,6 +215,7 @@ contract MultiMessageSender {
address _target,
bytes calldata _callData,
uint256 _nativeValue,
uint256 _expiration,
address[] memory _excludedAdapters
) private {
LocalCallVars memory v;
Expand Down Expand Up @@ -246,10 +270,8 @@ contract MultiMessageSender {
/// @dev increments nonce
++nonce;

v.msgExpiration = block.timestamp + gac.getMsgExpiryTime();

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

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

Expand Down Expand Up @@ -283,7 +305,7 @@ contract MultiMessageSender {
}

emit MultiMessageMsgSent(
v.msgId, nonce, _dstChainId, _target, _callData, v.msgExpiration, v.adapters, v.adapterSuccess
v.msgId, nonce, _dstChainId, _target, _callData, _nativeValue, _expiration, v.adapters, v.adapterSuccess
);
}

Expand Down
15 changes: 0 additions & 15 deletions src/controllers/GAC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ contract GAC is IGAC, Ownable {
STATE VARIABLES
//////////////////////////////////////////////////////////////*/
uint256 public dstGasLimit;
uint256 public msgExpiration;

/// @dev is the address to receive value refunds from remoteCall
address public refundAddress;
Expand Down Expand Up @@ -83,15 +82,6 @@ contract GAC is IGAC, Ownable {
emit DstGasLimitUpdated(oldLimit, _gasLimit);
}

/// @inheritdoc IGAC
function setMsgExpiryTime(uint256 _timeInSeconds) external override onlyOwner {
if (_timeInSeconds == 0) {
revert Error.ZERO_EXPIRATION_TIME();
}

msgExpiration = _timeInSeconds;
}

/// @inheritdoc IGAC
function setRefundAddress(address _refundAddress) external override onlyOwner {
if (_refundAddress == address(0)) {
Expand Down Expand Up @@ -124,11 +114,6 @@ contract GAC is IGAC, Ownable {
_gasLimit = dstGasLimit;
}

/// @inheritdoc IGAC
function getMsgExpiryTime() external view override returns (uint256 _expiration) {
_expiration = msgExpiration;
}

/// @inheritdoc IGAC
function getRefundAddress() external view override returns (address _refundAddress) {
_refundAddress = refundAddress;
Expand Down
7 changes: 0 additions & 7 deletions src/interfaces/IGAC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ interface IGAC {
/// @param _gasLimit is the limit to be set
function setGlobalMsgDeliveryGasLimit(uint256 _gasLimit) external;

/// @dev sets the message expiry time
/// @param _timeInSeconds is the expiry time for the message on dst chain
function setMsgExpiryTime(uint256 _timeInSeconds) external;

/// @dev sets the refund address for gas refunds
/// @param _refundAddress is the address to receive refunds from MMA sender
function setRefundAddress(address _refundAddress) external;
Expand Down Expand Up @@ -70,9 +66,6 @@ interface IGAC {
/// @dev returns the multi message receiver on the chain
function getMultiMessageReceiver(uint256 _chainId) external view returns (address _mmaReceiver);

/// @dev returns the expiry time of message from the time of dispatch
function getMsgExpiryTime() external view returns (uint256 _expiration);

/// @dev returns the refund address
function getRefundAddress() external view returns (address _refundAddress);
}
12 changes: 9 additions & 3 deletions src/libraries/Error.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ library Error {
/// @dev is thrown when input is zero address
error ZERO_ADDRESS_INPUT();

/// @dev is thrown when quorum is zero
error ZERO_QUORUM();

/// @dev is thrown if the length of two arrays are mismatched
error ARRAY_LENGTH_MISMATCHED();

Expand All @@ -35,9 +38,6 @@ library Error {
/// @dev is thrown if bridge adapter already delivered the message to multi message receiver
error DUPLICATE_MESSAGE_DELIVERY_BY_ADAPTER();

/// @dev is thrown if expiration time is zero
error ZERO_EXPIRATION_TIME();

/// @dev is thrown if quorum threshold is greater than receiver adapters
error INVALID_QUORUM_THRESHOLD();

Expand All @@ -62,6 +62,12 @@ library Error {
/// @dev is thrown if caller is not admin of timelock
error CALLER_NOT_ADMIN();

/// @dev is thrown if the expiration is less than minimum expiration
error INVALID_EXPIRATION_MIN();

/// @dev is thrown if the delay is more than maximum delay
error INVALID_EXPIRATION_MAX();

/*/////////////////////////////////////////////////////////////////
ADAPTER ERRORS
////////////////////////////////////////////////////////////////*/
Expand Down
Loading

0 comments on commit ff00c1b

Please sign in to comment.