-
Notifications
You must be signed in to change notification settings - Fork 18
/
Locker.sol
61 lines (48 loc) · 2.63 KB
/
Locker.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
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8;
import "rainbow-bridge-sol/nearprover/contracts/INearProver.sol";
import "rainbow-bridge-sol/nearprover/contracts/ProofDecoder.sol";
import "rainbow-bridge-sol/nearbridge/contracts/Borsh.sol";
contract Locker {
using Borsh for Borsh.Data;
using ProofDecoder for Borsh.Data;
INearProver public prover;
bytes public nearTokenFactory;
/// Proofs from blocks that are below the acceptance height will be rejected.
// If `minBlockAcceptanceHeight` value is zero - proofs from block with any height are accepted.
uint64 public minBlockAcceptanceHeight;
// OutcomeReciptId -> Used
mapping(bytes32 => bool) public usedProofs;
constructor(bytes memory _nearTokenFactory, INearProver _prover, uint64 _minBlockAcceptanceHeight) {
require(_nearTokenFactory.length > 0, "Invalid Near Token Factory address");
require(address(_prover) != address(0), "Invalid Near prover address");
nearTokenFactory = _nearTokenFactory;
prover = _prover;
minBlockAcceptanceHeight = _minBlockAcceptanceHeight;
}
/// Parses the provided proof and consumes it if it's not already used.
/// The consumed event cannot be reused for future calls.
function _parseAndConsumeProof(bytes memory proofData, uint64 proofBlockHeight)
internal
returns (ProofDecoder.ExecutionStatus memory result)
{
require(prover.proveOutcome(proofData, proofBlockHeight), "Proof should be valid");
// Unpack the proof and extract the execution outcome.
Borsh.Data memory borshData = Borsh.from(proofData);
ProofDecoder.FullOutcomeProof memory fullOutcomeProof = borshData.decodeFullOutcomeProof();
borshData.done();
require(
fullOutcomeProof.block_header_lite.inner_lite.height >= minBlockAcceptanceHeight,
"Proof is from the ancient block"
);
bytes32 receiptId = fullOutcomeProof.outcome_proof.outcome_with_id.outcome.receipt_ids[0];
require(!usedProofs[receiptId], "The burn event proof cannot be reused");
usedProofs[receiptId] = true;
require(keccak256(fullOutcomeProof.outcome_proof.outcome_with_id.outcome.executor_id)
== keccak256(nearTokenFactory),
"Can only unlock tokens from the linked proof producer on Near blockchain");
result = fullOutcomeProof.outcome_proof.outcome_with_id.outcome.status;
require(!result.failed, "Cannot use failed execution outcome for unlocking the tokens");
require(!result.unknown, "Cannot use unknown execution outcome for unlocking the tokens");
}
}