@@ -23,18 +23,24 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
2323 // ************************************* //
2424
2525 struct Claim {
26+ bytes32 messageHash;
2627 address bridger;
2728 uint256 claimedAt;
2829 uint256 claimDeposit;
29- bool relayed ;
30+ bool verified ;
3031 }
3132
3233 struct Challenge {
3334 address challenger;
3435 uint256 challengedAt;
3536 uint256 challengeDeposit;
37+ }
38+
39+ struct Ticket {
40+ Claim claim;
41+ Challenge challenge;
3642 bool relayed;
37- }
43+ }
3844
3945 // ************************************* //
4046 // * Storage * //
@@ -43,129 +49,135 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
4349 uint256 public override claimDeposit;
4450 uint256 public override challengeDeposit;
4551 uint256 public override challengeDuration;
46- uint256 public override safeBridgeTimeout;
47- mapping (bytes32 => Claim) public claims; // The claims by message hash.
48- mapping (bytes32 => Challenge) public challenges; // The challenges by message hash.
52+ mapping (uint256 => Ticket) public tickets; // The tickets by ticketID.
4953
5054 // ************************************* //
5155 // * Events * //
5256 // ************************************* //
5357
54- event ClaimReceived (bytes32 indexed messageHash , uint256 claimedAt );
55- event ClaimChallenged (bytes32 indexed _messageHash , uint256 challengedAt );
58+ event ClaimReceived (uint256 indexed _ticketID , bytes32 indexed messageHash , uint256 claimedAt );
59+ event ClaimChallenged (uint256 indexed _ticketID , bytes32 indexed _messageHash , uint256 challengedAt );
5660
5761 constructor (
5862 address _governor ,
5963 address _safeBridgeSender ,
6064 address _inbox ,
6165 uint256 _claimDeposit ,
6266 uint256 _challengeDeposit ,
63- uint256 _challengeDuration ,
64- uint256 _safeBridgeTimeout
67+ uint256 _challengeDuration
6568 ) SafeBridgeReceiverOnEthereum (_governor, _safeBridgeSender, _inbox) {
6669 claimDeposit = _claimDeposit;
6770 challengeDeposit = _challengeDeposit;
6871 challengeDuration = _challengeDuration;
69- safeBridgeTimeout - _safeBridgeTimeout;
7072 }
7173
7274 // ************************************* //
7375 // * State Modifiers * //
7476 // ************************************* //
7577
76- function claim (bytes32 _messageHash ) external payable override {
78+ function claim (uint256 _ticketID , bytes32 _messageHash ) external payable override {
7779 require (msg .value >= claimDeposit, "Not enough claim deposit " );
78- require (claims[_messageHash]. bridger == address (0 ), "Claimed already made " );
80+ require (tickets[_ticketID].claim. bridger == address (0 ), "Claim already made " );
7981
80- claims[_messageHash] = Claim ({
82+ tickets[_ticketID].claim = Claim ({
83+ messageHash: _messageHash,
8184 bridger: msg .sender ,
8285 claimedAt: block .timestamp ,
8386 claimDeposit: msg .value ,
84- relayed : false
87+ verified : false
8588 });
8689
87- emit ClaimReceived (_messageHash, block .timestamp );
90+ emit ClaimReceived (_ticketID, _messageHash, block .timestamp );
8891 }
8992
90- function challenge (bytes32 _messageHash ) external payable override {
91- Claim memory claim = claims[_messageHash ];
92- require (claim.bridger != address (0 ), "Claim does not exist " );
93- require (block .timestamp - claim.claimedAt < challengeDuration, "Challenge period over " );
93+ function challenge (uint256 _ticketID ) external payable override {
94+ Ticket memory ticket = tickets[_ticketID ];
95+ require (ticket. claim.bridger != address (0 ), "Claim does not exist " );
96+ require (block .timestamp - ticket. claim.claimedAt < challengeDuration, "Challenge period over " );
9497 require (msg .value >= challengeDeposit, "Not enough challenge deposit " );
95- require (challenges[_messageHash] .challenger == address (0 ), "Claim already challenged " );
98+ require (ticket.challenge .challenger == address (0 ), "Claim already challenged " );
9699
97- challenges[_messageHash] = Challenge ({
100+ ticket.challenge = Challenge ({
98101 challenger: msg .sender ,
99102 challengedAt: block .timestamp ,
100- challengeDeposit: msg .value ,
101- relayed: false
103+ challengeDeposit: msg .value
102104 });
103105
104- emit ClaimChallenged (_messageHash , block .timestamp );
106+ emit ClaimChallenged (_ticketID, ticket.claim.messageHash , block .timestamp );
105107 }
106108
107- function verifyAndRelay (bytes32 _messageHash , bytes memory _encodedData ) external override {
108- require ( keccak256 (_encodedData) == _messageHash, " Invalid hash " );
109-
110- Claim storage claim = claims[_messageHash];
111- require (claim.bridger != address ( 0 ), " Claim does not exist " );
112- require (claim.claimedAt + challengeDuration < block . timestamp , "Challenge period not over " );
113- require (claim.relayed == false , " Message already relayed " );
114- require (challenges[_messageHash].challenger == address ( 0 ), " Claim is challenged " ) ;
115-
116- // Decode the receiver address from the data encoded by the IFastBridgeSender
117- ( address receiver , bytes memory data ) = abi.decode (_encodedData, ( address , bytes ) );
118- ( bool success , ) = address (receiver). call (data );
119- require (success, " Failed to call contract " );
120-
121- claim.relayed = true ;
109+ function verifyAndRelay (
110+ uint256 _ticketID ,
111+ bytes32 _messageHash ,
112+ bytes memory _messageData
113+ ) external override {
114+ require (_verify (_messageHash, _ticketID, _messageData) , "Invalid hash " );
115+
116+ Ticket memory ticket = tickets[_ticketID] ;
117+ require (ticket.claim.bridger != address ( 0 ), " Claim does not exist " );
118+ require (ticket.claim.claimedAt + challengeDuration < block . timestamp , " Challenge period not over " );
119+ require (ticket.challenge.challenger == address ( 0 ), " Claim is challenged " );
120+ require (ticket.relayed == false , " Message already relayed " );
121+
122+ ticket.relayed = true ;
123+ require ( _relay (_messageData), " Failed to call contract " ); // Checks-Effects-Interaction
122124 }
123125
124- function verifyAndRelaySafe (bytes32 _messageHash , bytes memory _encodedData ) external override {
126+ function verifyAndRelaySafe (
127+ uint256 _ticketID ,
128+ bytes32 _messageHash ,
129+ bytes memory _messageData
130+ ) external override {
125131 require (isSentBySafeBridge (), "Access not allowed: SafeBridgeSender only. " );
132+ require (_verify (_messageHash, _ticketID, _messageData), "Invalid hash " );
126133
127- Challenge storage challenge = challenges[_messageHash];
128- Claim storage claim = claims[_messageHash];
129- require (claim.relayed != true , "Claim already relayed " );
130- require (challenge.relayed != true , "Challenge already relayed " );
134+ Ticket memory ticket = tickets[_ticketID];
135+ require (ticket.relayed == false , "Message already relayed " );
131136
132- // Decode the receiver address from the data encoded by the SafeBridgeSenderToEthereum
133- ( address receiver , bytes memory data ) = abi.decode (_encodedData, ( address , bytes ));
134- ( bool success , ) = address (receiver). call (data) ;
135- require (success, " Failed to call contract " );
137+ // Claim assessment if any
138+ if (ticket.claim.bridger != address ( 0 ) && ticket.claim.messageHash == _messageHash) {
139+ ticket.claim.verified = true ;
140+ }
136141
137- challenge.relayed == true ;
142+ ticket.relayed = true ;
143+ require (_relay (_messageData), "Failed to call contract " ); // Checks-Effects-Interaction
138144 }
139145
140- function withdrawClaimDeposit (bytes32 _messageHash ) external override {
141- Claim storage claim = claims[_messageHash];
142- require (claim.bridger != address (0 ), "Claim does not exist " );
143- require (claim.relayed == true , "Claim not relayed yet " );
144-
145- uint256 amount = claim.claimDeposit;
146- claim.claimDeposit = 0 ;
147- payable (claim.bridger).send (amount);
146+ function withdrawClaimDeposit (uint256 _ticketID ) external override {
147+ Ticket memory ticket = tickets[_ticketID];
148+ require (ticket.relayed == true , "Message not relayed yet " );
149+ require (ticket.claim.bridger != address (0 ), "Claim does not exist " );
150+ require (ticket.claim.verified == true , "Claim not verified: deposit forfeited " );
151+
152+ uint256 amount = ticket.claim.claimDeposit + ticket.challenge.challengeDeposit;
153+ ticket.claim.claimDeposit = 0 ;
154+ ticket.challenge.challengeDeposit = 0 ;
155+ payable (ticket.claim.bridger).send (amount); // Use of send to prevent reverting fallback. User is responsibility for accepting ETH.
156+ // Checks-Effects-Interaction
148157 }
149158
150- function withdrawChallengeDeposit (bytes32 _messageHash ) external override {
151- Challenge storage challenge = challenges[_messageHash];
152- require (challenge.challenger != address (0 ), "Challenge does not exist " );
153- require (challenge.relayed == true || block .timestamp > challenge.challengedAt + safeBridgeTimeout, "Challenge not relayed or timed out " );
154-
155- uint256 amount = challenge.challengeDeposit + claims[_messageHash].claimDeposit;
156- challenge.challengeDeposit = 0 ;
157- payable (challenge.challenger).send (amount);
159+ function withdrawChallengeDeposit (uint256 _ticketID ) external override {
160+ Ticket memory ticket = tickets[_ticketID];
161+ require (ticket.relayed == true , "Message not relayed " );
162+ require (ticket.challenge.challenger != address (0 ), "Challenge does not exist " );
163+ require (ticket.claim.verified == false , "Claim verified: deposit forfeited " );
164+
165+ uint256 amount = ticket.claim.claimDeposit + ticket.challenge.challengeDeposit;
166+ ticket.claim.claimDeposit = 0 ;
167+ ticket.challenge.challengeDeposit = 0 ;
168+ payable (ticket.challenge.challenger).send (amount); // Use of send to prevent reverting fallback. User is responsibility for accepting ETH.
169+ // Checks-Effects-Interaction
158170 }
159171
160172 // ************************************* //
161173 // * Public Views * //
162174 // ************************************* //
163175
164- function challengePeriod (bytes32 _messageHash ) public view returns (uint256 start , uint256 end ) {
165- Claim storage claim = claims[_messageHash ];
166- require (claim.bridger != address (0 ), "Claim does not exist " );
176+ function challengePeriod (uint256 _ticketID ) public view returns (uint256 start , uint256 end ) {
177+ Ticket memory ticket = tickets[_ticketID ];
178+ require (ticket. claim.bridger != address (0 ), "Claim does not exist " );
167179
168- start = claim.claimedAt;
180+ start = ticket. claim.claimedAt;
169181 end = start + challengeDuration;
170182 return (start, end);
171183 }
@@ -174,19 +186,33 @@ contract FastBridgeReceiverOnEthereum is SafeBridgeReceiverOnEthereum, IFastBrid
174186 // * Governance * //
175187 // ************************ //
176188
177- function setClaimDeposit (uint256 _claimDeposit ) external onlyByGovernor {
189+ function changeClaimDeposit (uint256 _claimDeposit ) external onlyByGovernor {
178190 claimDeposit = _claimDeposit;
179191 }
180192
181- function setChallengeDeposit (uint256 _challengeDeposit ) external onlyByGovernor {
193+ function changeChallengeDeposit (uint256 _challengeDeposit ) external onlyByGovernor {
182194 challengeDeposit = _challengeDeposit;
183195 }
184196
185- function setChallengePeriodDuration (uint256 _challengeDuration ) external onlyByGovernor {
197+ function changeChallengePeriodDuration (uint256 _challengeDuration ) external onlyByGovernor {
186198 challengeDuration = _challengeDuration;
187199 }
188200
189- function setSafeBridgeTimeout (uint256 _safeBridgeTimeout ) external onlyByGovernor {
190- safeBridgeTimeout = _safeBridgeTimeout;
201+ // ************************ //
202+ // * Internal * //
203+ // ************************ //
204+
205+ function _verify (
206+ bytes32 _expectedHash ,
207+ uint256 _ticketID ,
208+ bytes memory _messageData
209+ ) internal pure returns (bool ) {
210+ return _expectedHash == keccak256 (abi.encode (_ticketID, _messageData));
211+ }
212+
213+ function _relay (bytes memory _messageData ) internal returns (bool success ) {
214+ // Decode the receiver address from the data encoded by the IFastBridgeSender
215+ (address receiver , bytes memory data ) = abi.decode (_messageData, (address , bytes ));
216+ (success, ) = address (receiver).call (data);
191217 }
192218}
0 commit comments