-
Notifications
You must be signed in to change notification settings - Fork 6
/
EthCustodian.sol
145 lines (127 loc) · 4.31 KB
/
EthCustodian.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8;
import 'rainbow-bridge-sol/nearbridge/contracts/AdminControlled.sol';
import 'rainbow-bridge-sol/nearbridge/contracts/Borsh.sol';
import 'rainbow-bridge-sol/nearprover/contracts/ProofDecoder.sol';
import { INearProver, ProofKeeper } from './ProofKeeper.sol';
contract EthCustodian is ProofKeeper, AdminControlled {
using Borsh for Borsh.Data;
uint constant UNPAUSED_ALL = 0;
uint constant PAUSED_DEPOSIT_TO_EVM = 1 << 0;
uint constant PAUSED_DEPOSIT_TO_NEAR = 1 << 1;
uint constant PAUSED_WITHDRAW = 1 << 2;
string constant MESSAGE_SEPARATOR = ':';
event Deposited (
address indexed sender,
string recipient,
uint256 amount,
uint256 fee
);
event Withdrawn(
address indexed recipient,
uint128 amount
);
// Function output from burning nETH on Near side.
struct BurnResult {
uint128 amount;
address recipient;
address ethCustodian;
}
/// EthCustodian is linked to the EVM on NEAR side.
/// It also links to the prover that it uses to withdraw the tokens.
constructor(
bytes memory _nearEvm,
INearProver _prover,
uint64 _minBlockAcceptanceHeight,
address _admin,
uint _pausedFlags
)
AdminControlled(_admin, _pausedFlags)
ProofKeeper(_nearEvm, _prover, _minBlockAcceptanceHeight)
{
}
/// Deposits the specified amount of provided ETH (except from the relayer's fee) into the smart contract.
/// `ethRecipientOnNear` - the ETH address of the recipient in NEAR EVM
/// `fee` - the amount of fee that will be paid to the near-relayer in nETH.
function depositToEVM(
string memory ethRecipientOnNear,
uint256 fee
)
external
payable
pausable(PAUSED_DEPOSIT_TO_EVM)
{
require(
fee < msg.value,
'The fee cannot be bigger than the transferred amount.'
);
string memory protocolMessage = string(
abi.encodePacked(
string(nearProofProducerAccount_),
MESSAGE_SEPARATOR, ethRecipientOnNear
)
);
emit Deposited(
msg.sender,
protocolMessage,
msg.value,
fee
);
}
/// Deposits the specified amount of provided ETH (except from the relayer's fee) into the smart contract.
/// `nearRecipientAccountId` - the AccountID of the recipient in NEAR
/// `fee` - the amount of fee that will be paid to the near-relayer in nETH.
function depositToNear(
string memory nearRecipientAccountId,
uint256 fee
)
external
payable
pausable(PAUSED_DEPOSIT_TO_NEAR)
{
require(
fee < msg.value,
'The fee cannot be bigger than the transferred amount.'
);
emit Deposited(
msg.sender,
nearRecipientAccountId,
msg.value,
fee
);
}
/// Withdraws the appropriate amount of ETH which is encoded in `proofData`
function withdraw(
bytes calldata proofData,
uint64 proofBlockHeight
)
external
pausable(PAUSED_WITHDRAW)
{
ProofDecoder.ExecutionStatus memory status = _parseAndConsumeProof(proofData, proofBlockHeight);
BurnResult memory result = _decodeBurnResult(status.successValue);
require(
result.ethCustodian == address(this),
'Can only withdraw coins that were expected for the current contract'
);
(bool success, ) = payable(result.recipient).call{value: result.amount}("");
require(success, 'The withdrawal attempt was unsuccessful');
emit Withdrawn(
result.recipient,
result.amount
);
}
function _decodeBurnResult(bytes memory data)
internal
pure
returns (BurnResult memory result)
{
Borsh.Data memory borshData = Borsh.from(data);
result.amount = borshData.decodeU128();
bytes20 recipient = borshData.decodeBytes20();
result.recipient = address(uint160(recipient));
bytes20 ethCustodian = borshData.decodeBytes20();
result.ethCustodian = address(uint160(ethCustodian));
borshData.done();
}
}