forked from Synthetixio/synthetix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSynthetixBridgeToBase.sol
111 lines (83 loc) · 4.22 KB
/
SynthetixBridgeToBase.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
pragma solidity ^0.5.16;
// Inheritance
import "./Owned.sol";
import "./MixinResolver.sol";
import "./MixinSystemSettings.sol";
import "./interfaces/ISynthetixBridgeToBase.sol";
// Internal references
import "./interfaces/ISynthetix.sol";
import "./interfaces/IIssuer.sol";
// solhint-disable indent
import "@eth-optimism/contracts/build/contracts/iOVM/bridge/iOVM_BaseCrossDomainMessenger.sol";
contract SynthetixBridgeToBase is Owned, MixinSystemSettings, ISynthetixBridgeToBase {
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
bytes32 private constant CONTRACT_EXT_MESSENGER = "ext:Messenger";
bytes32 private constant CONTRACT_SYNTHETIX = "Synthetix";
bytes32 private constant CONTRACT_ISSUER = "Issuer";
bytes32 private constant CONTRACT_BASE_SYNTHETIXBRIDGETOOPTIMISM = "base:SynthetixBridgeToOptimism";
// ========== CONSTRUCTOR ==========
constructor(address _owner, address _resolver) public Owned(_owner) MixinSystemSettings(_resolver) {}
//
// ========== INTERNALS ============
function messenger() internal view returns (iOVM_BaseCrossDomainMessenger) {
return iOVM_BaseCrossDomainMessenger(requireAndGetAddress(CONTRACT_EXT_MESSENGER));
}
function synthetix() internal view returns (ISynthetix) {
return ISynthetix(requireAndGetAddress(CONTRACT_SYNTHETIX));
}
function issuer() internal view returns (IIssuer) {
return IIssuer(requireAndGetAddress(CONTRACT_ISSUER));
}
function synthetixBridgeToOptimism() internal view returns (address) {
return requireAndGetAddress(CONTRACT_BASE_SYNTHETIXBRIDGETOOPTIMISM);
}
function onlyAllowFromOptimism() internal view {
// ensure function only callable from the L2 bridge via messenger (aka relayer)
iOVM_BaseCrossDomainMessenger _messenger = messenger();
require(msg.sender == address(_messenger), "Only the relayer can call this");
require(_messenger.xDomainMessageSender() == synthetixBridgeToOptimism(), "Only the L1 bridge can invoke");
}
modifier onlyOptimismBridge() {
onlyAllowFromOptimism();
_;
}
// ========== VIEWS ==========
function resolverAddressesRequired() public view returns (bytes32[] memory) {
bytes32[] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired();
bytes32[] memory addresses = new bytes32[](4);
addresses[0] = CONTRACT_EXT_MESSENGER;
addresses[1] = CONTRACT_SYNTHETIX;
addresses[2] = CONTRACT_BASE_SYNTHETIXBRIDGETOOPTIMISM;
addresses[3] = CONTRACT_ISSUER;
return combineArrays(existingAddresses, addresses);
}
// ========== PUBLIC FUNCTIONS =========
// invoked by user on L2
function initiateWithdrawal(uint amount) external {
require(issuer().debtBalanceOf(msg.sender, "sUSD") == 0, "Cannot withdraw with debt");
// instruct L2 Synthetix to burn this supply
synthetix().burnSecondary(msg.sender, amount);
// create message payload for L1
bytes memory messageData = abi.encodeWithSignature("completeWithdrawal(address,uint256)", msg.sender, amount);
// relay the message to Bridge on L1 via L2 Messenger
messenger().sendMessage(synthetixBridgeToOptimism(), messageData, uint32(getCrossDomainMessageGasLimit()));
emit WithdrawalInitiated(msg.sender, amount);
}
// ========= RESTRICTED FUNCTIONS ==============
// invoked by Messenger on L2
function completeDeposit(address account, uint amount) external onlyOptimismBridge {
// now tell Synthetix to mint these tokens, deposited in L1, into the same account for L2
synthetix().mintSecondary(account, amount);
emit MintedSecondary(account, amount);
}
// invoked by Messenger on L2
function completeRewardDeposit(uint amount) external onlyOptimismBridge {
// now tell Synthetix to mint these tokens, deposited in L1, into reward escrow on L2
synthetix().mintSecondaryRewards(amount);
emit MintedSecondaryRewards(amount);
}
// ========== EVENTS ==========
event MintedSecondary(address indexed account, uint amount);
event MintedSecondaryRewards(uint amount);
event WithdrawalInitiated(address indexed account, uint amount);
}