Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: forbid portal contract to call mnt token directly #98

Merged
merged 1 commit into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 32 additions & 11 deletions op-bindings/bindings/l1crossdomainmessenger.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion op-bindings/bindings/l1crossdomainmessenger_more.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion op-bindings/bindings/l1standardbridge.go

Large diffs are not rendered by default.

43 changes: 32 additions & 11 deletions op-bindings/bindings/l2crossdomainmessenger.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion op-bindings/bindings/l2crossdomainmessenger_more.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion op-bindings/bindings/l2standardbridge.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion op-bindings/bindings/l2standardbridge_more.go

Large diffs are not rendered by default.

39 changes: 35 additions & 4 deletions op-bindings/bindings/l2tol1messagepasser.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion op-bindings/bindings/l2tol1messagepasser_more.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion op-bindings/bindings/optimismportal.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion op-bindings/bindings/optimismportal_more.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,9 @@ func NewL2ImmutableConfig(config *DeployConfig) (immutables.ImmutableConfig, err
immutable["LegacyERC20MNT"] = immutables.ImmutableValues{
"L1_MNT_ADDRESS": config.L1MantleToken,
}
immutable["L2ToL1MessagePasser"] = immutables.ImmutableValues{
"L1_MNT_ADDRESS": config.L1MantleToken,
}

return immutable, nil
}
Expand Down
10 changes: 8 additions & 2 deletions op-chain-ops/immutables/immutables.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ func BuildOptimism(immutable ImmutableConfig) (DeploymentResults, error) {
},
{
Name: "L2ToL1MessagePasser",
Args: []interface{}{
immutable["L2ToL1MessagePasser"]["L1_MNT_ADDRESS"],
},
},
{
Name: "SequencerFeeVault",
Expand Down Expand Up @@ -190,8 +193,11 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep
}
_, tx, _, err = bindings.DeployL2StandardBridge(opts, backend, otherBridge, L1MNT)
case "L2ToL1MessagePasser":
// No arguments required for L2ToL1MessagePasser
_, tx, _, err = bindings.DeployL2ToL1MessagePasser(opts, backend)
L1MNT, ok := deployment.Args[0].(common.Address)
if !ok {
return nil, fmt.Errorf("invalid type for L1 MNT")
}
_, tx, _, err = bindings.DeployL2ToL1MessagePasser(opts, backend, L1MNT)
case "SequencerFeeVault":
recipient, ok := deployment.Args[0].(common.Address)
if !ok {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,17 +246,16 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, Semver {

return;
}
bool mntSuccess = true;
if (_mntValue!=0){
mntSuccess = IERC20(L1_MNT_ADDRESS).approve(_target, _mntValue);
IERC20(L1_MNT_ADDRESS).approve(_target, _mntValue);
}
xDomainMsgSender = _sender;
bool success = SafeCall.call(_target, gasleft() - RELAY_RESERVED_GAS, _ethValue, _message);
xDomainMsgSender = Constants.DEFAULT_L2_SENDER;
if (_mntValue!=0){
mntSuccess = IERC20(L1_MNT_ADDRESS).approve(_target, 0);
IERC20(L1_MNT_ADDRESS).approve(_target, 0);
}
if (success && mntSuccess) {
if (success) {
successfulMessages[versionedHash] = true;
emit RelayedMessage(versionedHash);
} else {
Expand Down
1 change: 1 addition & 0 deletions packages/contracts-bedrock/contracts/L1/OptimismPortal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
if (_tx.mntValue>0){
l1mntSuccess = IERC20(L1_MNT_ADDRESS).transfer(_tx.target, _tx.mntValue);
}
require(_tx.target != L1_MNT_ADDRESS, "Directly calling MNT Token is forbidden");
bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.ethValue, _tx.data);
// Reset the l2Sender back to the default value.
l2Sender = Constants.DEFAULT_L2_SENDER;
Expand Down
10 changes: 9 additions & 1 deletion packages/contracts-bedrock/contracts/L2/L2ToL1MessagePasser.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ contract L2ToL1MessagePasser is Semver {
*/
uint16 public constant MESSAGE_VERSION = 1;

/**
* @notice MNT Token Address on Ethereum
*/
address public immutable L1_MNT_ADDRESS;

/**
* @notice Includes the message hashes for all withdrawals
*/
Expand Down Expand Up @@ -73,7 +78,9 @@ contract L2ToL1MessagePasser is Semver {
/**
* @custom:semver 1.0.0
*/
constructor() Semver(1, 0, 0) {}
constructor(address _l1mnt) Semver(1, 0, 0) {
L1_MNT_ADDRESS = _l1mnt;
}

/**
* @notice Allows users to withdraw MNT by sending directly to this contract.
Expand Down Expand Up @@ -108,6 +115,7 @@ contract L2ToL1MessagePasser is Semver {
uint256 _gasLimit,
bytes memory _data
) public payable {
require(_target != L1_MNT_ADDRESS, "Directly calling MNT Token is forbidden");
if (_ethValue != 0) {
OptimismMintableERC20(Predeploys.BVM_ETH).burn(msg.sender, _ethValue);
}
Expand Down
28 changes: 10 additions & 18 deletions packages/contracts-bedrock/contracts/test/CommonTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ contract L2OutputOracle_Initializer is CommonTest {
// Test data
uint256 initL1Time;

L1MantleToken internal l1MNTImpl;
L1MantleToken internal l1MNT;

event OutputProposed(
bytes32 indexed outputRoot,
uint256 indexed l2OutputIndex,
Expand All @@ -128,6 +131,12 @@ contract L2OutputOracle_Initializer is CommonTest {

function setUp() public virtual override {
super.setUp();

vm.prank(multisig);
l1MNTImpl = new L1MantleToken();
l1MNT = L1MantleToken(address(l1MNTImpl));
vm.label(address(l1MNT), "L1MantleToken");

guardian = makeAddr("guardian");

// By default the first block has timestamp and number zero, which will cause underflows in the
Expand Down Expand Up @@ -155,7 +164,7 @@ contract L2OutputOracle_Initializer is CommonTest {
vm.label(address(oracle), "L2OutputOracle");

// Set the L2ToL1MessagePasser at the correct address
vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser()).code);
vm.etch(Predeploys.L2_TO_L1_MESSAGE_PASSER, address(new L2ToL1MessagePasser(address(l1MNT))).code);

vm.label(Predeploys.L2_TO_L1_MESSAGE_PASSER, "L2ToL1MessagePasser");
}
Expand All @@ -164,26 +173,9 @@ contract L2OutputOracle_Initializer is CommonTest {
contract MNTToken_Initializer is L2OutputOracle_Initializer {
using stdStorage for StdStorage;

// Test target
L1MantleToken internal l1MNTImpl;
L1MantleToken internal l1MNT;


function setUp() public virtual override {
super.setUp();


vm.prank(multisig);
l1MNTImpl = new L1MantleToken();
// Proxy proxy = new Proxy(multisig);
// vm.prank(multisig);
// proxy.upgradeToAndCall(
// address(l1MNTImpl),
// abi.encodeWithSelector(L1MantleToken.initialize.selector, 1000000 * 10 ** 18, multisig)
// );

l1MNT = L1MantleToken(address(l1MNTImpl));
vm.label(address(l1MNT), "L1MantleToken");
}

function dealL1MNT(address _target,uint256 _amount) public {
Expand Down