@keep-network/tbtc-v2 0.1.0 → 0.1.1-dev.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/artifacts/.chainId +1 -1
- package/artifacts/TBTC.json +35 -35
- package/artifacts/TBTCToken.json +737 -0
- package/artifacts/VendingMachine.json +31 -31
- package/artifacts/solcInputs/50a502fc3a2e83304e38e355c5860eb6.json +134 -0
- package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
- package/build/contracts/bank/Bank.sol/Bank.dbg.json +4 -0
- package/build/contracts/bank/Bank.sol/Bank.json +537 -0
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +4 -0
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +10 -0
- package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +4 -0
- package/build/contracts/bridge/Bridge.sol/Bridge.json +473 -0
- package/build/contracts/bridge/Bridge.sol/IRelay.dbg.json +4 -0
- package/build/contracts/bridge/Bridge.sol/IRelay.json +37 -0
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
- package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
- package/build/contracts/token/TBTC.sol/TBTC.json +4 -4
- package/build/contracts/vault/IVault.sol/IVault.dbg.json +4 -0
- package/build/contracts/vault/IVault.sol/IVault.json +47 -0
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +4 -0
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +181 -0
- package/contracts/bank/Bank.sol +389 -0
- package/contracts/bridge/BitcoinTx.sol +125 -0
- package/contracts/bridge/Bridge.sol +804 -0
- package/contracts/vault/IVault.sol +60 -0
- package/contracts/vault/TBTCVault.sol +146 -0
- package/deploy/00_resolve_tbtc_v1_token.ts +1 -1
- package/deploy/01_deploy_tbtc_v2_token.ts +8 -1
- package/deploy/02_deploy_vending_machine.ts +7 -0
- package/export.json +189 -88
- package/package.json +27 -16
- package/artifacts/solcInputs/7cc3eda3cb3ff2522d18b5e7b31ea228.json +0 -104
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
// ██████████████ ▐████▌ ██████████████
|
|
4
|
+
// ██████████████ ▐████▌ ██████████████
|
|
5
|
+
// ▐████▌ ▐████▌
|
|
6
|
+
// ▐████▌ ▐████▌
|
|
7
|
+
// ██████████████ ▐████▌ ██████████████
|
|
8
|
+
// ██████████████ ▐████▌ ██████████████
|
|
9
|
+
// ▐████▌ ▐████▌
|
|
10
|
+
// ▐████▌ ▐████▌
|
|
11
|
+
// ▐████▌ ▐████▌
|
|
12
|
+
// ▐████▌ ▐████▌
|
|
13
|
+
// ▐████▌ ▐████▌
|
|
14
|
+
// ▐████▌ ▐████▌
|
|
15
|
+
|
|
16
|
+
pragma solidity 0.8.4;
|
|
17
|
+
|
|
18
|
+
/// @title Bank Vault interface
|
|
19
|
+
/// @notice `IVault` is an interface for a smart contract consuming Bank
|
|
20
|
+
/// balances of other contracts or externally owned accounts (EOA).
|
|
21
|
+
interface IVault {
|
|
22
|
+
/// @notice Called by the Bank in `approveBalanceAndCall` function after
|
|
23
|
+
/// the balance `owner` approved `amount` of their balance in the
|
|
24
|
+
/// Bank for the vault. This way, the depositor can approve balance
|
|
25
|
+
/// and call the vault to use the approved balance in a single
|
|
26
|
+
/// transaction.
|
|
27
|
+
/// @param owner Address of the Bank balance owner who approved their
|
|
28
|
+
/// balance to be used by the vault
|
|
29
|
+
/// @param amount The amount of the Bank balance approved by the owner
|
|
30
|
+
/// to be used by the vault
|
|
31
|
+
// @dev The implementation must ensure this function can only be called
|
|
32
|
+
/// by the Bank. The Bank does _not_ guarantee that the `amount`
|
|
33
|
+
/// approved by the `owner` currently exists on their balance. That is,
|
|
34
|
+
/// the `owner` could approve more balance than they currently have.
|
|
35
|
+
/// This works the same as `Bank.approve` function. The vault must
|
|
36
|
+
/// ensure the actual balance is checked before performing any action
|
|
37
|
+
/// based on it.
|
|
38
|
+
function receiveBalanceApproval(address owner, uint256 amount) external;
|
|
39
|
+
|
|
40
|
+
/// @notice Called by the Bank in `increaseBalanceAndCall` function after
|
|
41
|
+
/// increasing the balance in the Bank for the vault. It happens in
|
|
42
|
+
/// the same transaction in which deposits were swept by the Bridge.
|
|
43
|
+
/// This allows the depositor to route their deposit revealed to the
|
|
44
|
+
/// Bridge to the particular smart contract (vault) in the same
|
|
45
|
+
/// transaction in which the deposit is revealed. This way, the
|
|
46
|
+
/// depositor does not have to execute additional transaction after
|
|
47
|
+
/// the deposit gets swept by the Bridge to approve and transfer
|
|
48
|
+
/// their balance to the vault.
|
|
49
|
+
/// @param depositors Addresses of depositors whose deposits have been swept
|
|
50
|
+
/// @param depositedAmounts Amounts deposited by individual depositors and
|
|
51
|
+
/// swept
|
|
52
|
+
/// @dev The implementation must ensure this function can only be called
|
|
53
|
+
/// by the Bank. The Bank guarantees that the vault's balance was
|
|
54
|
+
/// increased by the sum of all deposited amounts before this function
|
|
55
|
+
/// is called, in the same transaction.
|
|
56
|
+
function receiveBalanceIncrease(
|
|
57
|
+
address[] calldata depositors,
|
|
58
|
+
uint256[] calldata depositedAmounts
|
|
59
|
+
) external;
|
|
60
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
// ██████████████ ▐████▌ ██████████████
|
|
4
|
+
// ██████████████ ▐████▌ ██████████████
|
|
5
|
+
// ▐████▌ ▐████▌
|
|
6
|
+
// ▐████▌ ▐████▌
|
|
7
|
+
// ██████████████ ▐████▌ ██████████████
|
|
8
|
+
// ██████████████ ▐████▌ ██████████████
|
|
9
|
+
// ▐████▌ ▐████▌
|
|
10
|
+
// ▐████▌ ▐████▌
|
|
11
|
+
// ▐████▌ ▐████▌
|
|
12
|
+
// ▐████▌ ▐████▌
|
|
13
|
+
// ▐████▌ ▐████▌
|
|
14
|
+
// ▐████▌ ▐████▌
|
|
15
|
+
|
|
16
|
+
pragma solidity 0.8.4;
|
|
17
|
+
|
|
18
|
+
import "./IVault.sol";
|
|
19
|
+
import "../bank/Bank.sol";
|
|
20
|
+
import "../token/TBTC.sol";
|
|
21
|
+
|
|
22
|
+
/// @title TBTC application vault
|
|
23
|
+
/// @notice TBTC is a fully Bitcoin-backed ERC-20 token pegged to the price of
|
|
24
|
+
/// Bitcoin. It facilitates Bitcoin holders to act on the Ethereum
|
|
25
|
+
/// blockchain and access the decentralized finance (DeFi) ecosystem.
|
|
26
|
+
/// TBTC Vault mints and redeems TBTC based on Bitcoin balances in the
|
|
27
|
+
/// Bank.
|
|
28
|
+
/// @dev TBTC Vault is the owner of TBTC token contract and is the only contract
|
|
29
|
+
/// minting the token.
|
|
30
|
+
contract TBTCVault is IVault {
|
|
31
|
+
Bank public bank;
|
|
32
|
+
TBTC public tbtcToken;
|
|
33
|
+
|
|
34
|
+
event Minted(address indexed to, uint256 amount);
|
|
35
|
+
|
|
36
|
+
event Redeemed(address indexed from, uint256 amount);
|
|
37
|
+
|
|
38
|
+
modifier onlyBank() {
|
|
39
|
+
require(msg.sender == address(bank), "Caller is not the Bank");
|
|
40
|
+
_;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
constructor(Bank _bank, TBTC _tbtcToken) {
|
|
44
|
+
require(
|
|
45
|
+
address(_bank) != address(0),
|
|
46
|
+
"Bank can not be the zero address"
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
require(
|
|
50
|
+
address(_tbtcToken) != address(0),
|
|
51
|
+
"TBTC token can not be the zero address"
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
bank = _bank;
|
|
55
|
+
tbtcToken = _tbtcToken;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// @notice Transfers the given `amount` of the Bank balance from caller
|
|
59
|
+
/// to TBTC Vault, and mints `amount` of TBTC to the caller.
|
|
60
|
+
/// @dev TBTC Vault must have an allowance for caller's balance in the Bank
|
|
61
|
+
/// for at least `amount`.
|
|
62
|
+
/// @param amount Amount of TBTC to mint
|
|
63
|
+
function mint(uint256 amount) external {
|
|
64
|
+
address minter = msg.sender;
|
|
65
|
+
require(
|
|
66
|
+
bank.balanceOf(minter) >= amount,
|
|
67
|
+
"Amount exceeds balance in the bank"
|
|
68
|
+
);
|
|
69
|
+
_mint(minter, amount);
|
|
70
|
+
bank.transferBalanceFrom(minter, address(this), amount);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// @notice Transfers the given `amount` of the Bank balance from the caller
|
|
74
|
+
/// to TBTC Vault and mints `amount` of TBTC to the caller.
|
|
75
|
+
/// @dev Can only be called by the Bank via `approveBalanceAndCall`.
|
|
76
|
+
/// @param owner The owner who approved their Bank balance
|
|
77
|
+
/// @param amount Amount of TBTC to mint
|
|
78
|
+
function receiveBalanceApproval(address owner, uint256 amount)
|
|
79
|
+
external
|
|
80
|
+
override
|
|
81
|
+
onlyBank
|
|
82
|
+
{
|
|
83
|
+
require(
|
|
84
|
+
bank.balanceOf(owner) >= amount,
|
|
85
|
+
"Amount exceeds balance in the bank"
|
|
86
|
+
);
|
|
87
|
+
_mint(owner, amount);
|
|
88
|
+
bank.transferBalanceFrom(owner, address(this), amount);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// @notice Mints the same amount of TBTC as the deposited amount for each
|
|
92
|
+
/// depositor in the array. Can only be called by the Bank after the
|
|
93
|
+
/// Bridge swept deposits and Bank increased balance for the
|
|
94
|
+
/// vault.
|
|
95
|
+
/// @dev Fails if `depositors` array is empty. Expects the length of
|
|
96
|
+
/// `depositors` and `depositedAmounts` is the same.
|
|
97
|
+
function receiveBalanceIncrease(
|
|
98
|
+
address[] calldata depositors,
|
|
99
|
+
uint256[] calldata depositedAmounts
|
|
100
|
+
) external override onlyBank {
|
|
101
|
+
require(depositors.length != 0, "No depositors specified");
|
|
102
|
+
for (uint256 i = 0; i < depositors.length; i++) {
|
|
103
|
+
_mint(depositors[i], depositedAmounts[i]);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// @notice Burns `amount` of TBTC from the caller's account and transfers
|
|
108
|
+
/// `amount` back to the caller's balance in the Bank.
|
|
109
|
+
/// @dev Caller must have at least `amount` of TBTC approved to
|
|
110
|
+
/// TBTC Vault.
|
|
111
|
+
/// @param amount Amount of TBTC to redeem
|
|
112
|
+
function redeem(uint256 amount) external {
|
|
113
|
+
_redeem(msg.sender, amount);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// @notice Burns `amount` of TBTC from the caller's account and transfers
|
|
117
|
+
/// `amount` back to the caller's balance in the Bank.
|
|
118
|
+
/// @dev This function is doing the same as `redeem` but it allows to
|
|
119
|
+
/// execute redemption without an additional approval transaction.
|
|
120
|
+
/// The function can be called only via `approveAndCall` of TBTC token.
|
|
121
|
+
/// @param from TBTC token holder executing redemption
|
|
122
|
+
/// @param amount Amount of TBTC to redeem
|
|
123
|
+
/// @param token TBTC token address
|
|
124
|
+
function receiveApproval(
|
|
125
|
+
address from,
|
|
126
|
+
uint256 amount,
|
|
127
|
+
address token,
|
|
128
|
+
bytes calldata
|
|
129
|
+
) external {
|
|
130
|
+
require(token == address(tbtcToken), "Token is not TBTC");
|
|
131
|
+
require(msg.sender == token, "Only TBTC caller allowed");
|
|
132
|
+
_redeem(from, amount);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// slither-disable-next-line calls-loop
|
|
136
|
+
function _mint(address minter, uint256 amount) internal {
|
|
137
|
+
emit Minted(minter, amount);
|
|
138
|
+
tbtcToken.mint(minter, amount);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function _redeem(address redeemer, uint256 amount) internal {
|
|
142
|
+
emit Redeemed(redeemer, amount);
|
|
143
|
+
tbtcToken.burnFrom(redeemer, amount);
|
|
144
|
+
bank.transferBalance(redeemer, amount);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -13,7 +13,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
|
|
13
13
|
} else if (hre.network.name !== "hardhat") {
|
|
14
14
|
throw new Error("deployed TBTCToken contract not found")
|
|
15
15
|
} else {
|
|
16
|
-
log(
|
|
16
|
+
log("deploying TBTCToken stub")
|
|
17
17
|
|
|
18
18
|
await deployments.deploy("TBTCToken", {
|
|
19
19
|
contract: "TestERC20",
|
|
@@ -6,10 +6,17 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
|
|
6
6
|
const { deploy } = deployments
|
|
7
7
|
const { deployer } = await getNamedAccounts()
|
|
8
8
|
|
|
9
|
-
await deploy("TBTC", {
|
|
9
|
+
const TBTC = await deploy("TBTC", {
|
|
10
10
|
from: deployer,
|
|
11
11
|
log: true,
|
|
12
12
|
})
|
|
13
|
+
|
|
14
|
+
if (hre.network.tags.tenderly) {
|
|
15
|
+
await hre.tenderly.verify({
|
|
16
|
+
name: "TBTC",
|
|
17
|
+
address: TBTC.address,
|
|
18
|
+
})
|
|
19
|
+
}
|
|
13
20
|
}
|
|
14
21
|
|
|
15
22
|
export default func
|
|
@@ -22,6 +22,13 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
|
|
22
22
|
VendingMachine.address,
|
|
23
23
|
deployer
|
|
24
24
|
)
|
|
25
|
+
|
|
26
|
+
if (hre.network.tags.tenderly) {
|
|
27
|
+
await hre.tenderly.verify({
|
|
28
|
+
name: "VendingMachine",
|
|
29
|
+
address: VendingMachine.address,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
export default func
|