Skip to content

Commit

Permalink
Don't return awaited promise in getUnnamedSigner
Browse files Browse the repository at this point in the history
Fix `@typescript-eslint/return-await` error returned by eslint.
  • Loading branch information
nkuba committed Dec 13, 2023
1 parent e21a50b commit 4139748
Show file tree
Hide file tree
Showing 14 changed files with 9,115 additions and 1 deletion.
185 changes: 185 additions & 0 deletions core/contracts/TbtcDepositor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

import {BTCUtils} from "@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol";

import "./Acre.sol";

import "hardhat/console.sol";

interface IBridge {
struct BitcoinTxInfo {
bytes4 version;
bytes inputVector;
bytes outputVector;
bytes4 locktime;
}

struct DepositRevealInfo {
uint32 fundingOutputIndex;
bytes8 blindingFactor;
bytes20 walletPubKeyHash;
bytes20 refundPubKeyHash;
bytes4 refundLocktime;
address vault;
bytes32 depositorExtraData;
}

struct DepositRequest {
address depositor;
uint64 amount;
uint32 revealedAt;
address vault;
uint64 treasuryFee;
uint32 sweptAt;
bytes32 depositorExtraData;
}

function revealDepositWithExtraData(
BitcoinTxInfo calldata fundingTx,
DepositRevealInfo calldata reveal
) external;

function deposits(
uint256 depositKey
) external view returns (DepositRequest memory);
}

interface ITBTCVault {
struct OptimisticMintingRequest {
// UNIX timestamp at which the optimistic minting was requested.
uint64 requestedAt;
// UNIX timestamp at which the optimistic minting was finalized.
// 0 if not yet finalized.
uint64 finalizedAt;
// TODO: This field is not included in the original struct. It would require upgrade.
uint256 optimisticMintFee;
}

function optimisticMintingRequests(
uint256 depositKey
) external returns (OptimisticMintingRequest memory);
}

// Extra Data 32 byte
// receiver - address - 20 byte
// referral - uint16 - 2 byte

contract TbtcDepositor {
// TODO: Do we need to import it?
using BTCUtils for bytes;

IBridge public bridge;
ITBTCVault public tbtcVault;
Acre public acre;

struct DepositRequest {
// UNIX timestamp at which the optimistic minting was requested.
uint64 requestedAt;
// UNIX timestamp at which the optimistic minting was finalized.
// 0 if not yet finalized.
uint64 finalizedAt;
}

mapping(uint256 => DepositRequest) public depositRequests;

constructor(IBridge _bridge, ITBTCVault _tbtcVault, Acre _acre) {
bridge = _bridge;
tbtcVault = _tbtcVault;
acre = _acre;
}

// TODO: Implement
function initializeDeposit(
IBridge.BitcoinTxInfo calldata fundingTx,
IBridge.DepositRevealInfo calldata reveal
) external {
bytes32 fundingTxHash = abi
.encodePacked(
fundingTx.version,
fundingTx.inputVector,
fundingTx.outputVector,
fundingTx.locktime
)
.hash256View();

DepositRequest storage request = depositRequests[
calculateDepositKey(fundingTxHash, reveal.fundingOutputIndex)
];

// TODO: Replace with custom errors
require(request.requestedAt == 0, "deposit already initialized");
request.requestedAt = uint64(block.timestamp);

bridge.revealDepositWithExtraData(fundingTx, reveal);
}

function finalizeDeposit(
bytes32 fundingTxHash,
uint32 fundingOutputIndex
) external {
uint256 depositKey = calculateDepositKey(
fundingTxHash,
fundingOutputIndex
);
DepositRequest storage request = depositRequests[depositKey];

require(request.requestedAt > 0, "deposit not initialized");
require(request.finalizedAt == 0, "deposit already finalized");

ITBTCVault.OptimisticMintingRequest
memory optimisticMintingRequest = tbtcVault
.optimisticMintingRequests(depositKey);

IBridge.DepositRequest memory bridgeDepositRequest = bridge.deposits(
depositKey
);

uint256 amount= bridgeDepositRequest.amount - bridgeDepositRequest.treasuryFee;
if (optimisticMintingRequest.requestedAt > 0) {
require(
optimisticMintingRequest.finalizedAt > 0,
"optimistic minting not yet finalized"
);
amount -= optimisticMintingRequest.optimisticMintFee;
} else {
require(
bridgeDepositRequest.sweptAt > 0,
"tbtc deposit not yet swept"
);
}

request.finalizedAt = uint64(block.timestamp);

// TODO: Consider decoding inline
(address receiver, uint16 referral) = decodeExtraData(
bridgeDepositRequest.depositorExtraData
);

IERC20(acre.asset()).approve(address(acre), amount);

// acre.stake(amount, receiver, referral);
}

/// @notice Calculates deposit key the same way as the Bridge contract.
/// The deposit key is computed as
/// `keccak256(fundingTxHash | fundingOutputIndex)`.
function calculateDepositKey(
bytes32 fundingTxHash,
uint32 fundingOutputIndex
) public pure returns (uint256) {
return
uint256(
keccak256(abi.encodePacked(fundingTxHash, fundingOutputIndex))
);
}

function decodeExtraData(
bytes32 extraData
) public pure returns (address receiver, uint16 referral) {
// First 20 bytes of extra data is receiver address.
receiver = address(uint160(bytes20(extraData)));
// Next 2 bytes of extra data is referral info.
referral = uint16(bytes2(extraData << (8 * 20)));
}
}
75 changes: 75 additions & 0 deletions core/contracts/test/BridgeStub.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

import {BTCUtils} from "@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol";
import {IBridge} from "../TbtcDepositor.sol";

contract BridgeStub is IBridge {
using BTCUtils for bytes;

mapping(uint256 => DepositRequest) dep;

uint64 depositTreasuryFeeDivisor = 2000; // 0.05%

function revealDepositWithExtraData(
BitcoinTxInfo calldata fundingTx,
DepositRevealInfo calldata reveal
) external {
bytes32 fundingTxHash = abi
.encodePacked(
fundingTx.version,
fundingTx.inputVector,
fundingTx.outputVector,
fundingTx.locktime
)
.hash256View();

DepositRequest storage deposit = dep[
calculateDepositKey(fundingTxHash, reveal.fundingOutputIndex)
];

require(deposit.revealedAt == 0, "Deposit already revealed");

bytes memory fundingOutput = fundingTx
.outputVector
.extractOutputAtIndex(reveal.fundingOutputIndex);

uint64 fundingOutputAmount = fundingOutput.extractValue();

deposit.amount = fundingOutputAmount;
deposit.depositor = msg.sender;
/* solhint-disable-next-line not-rely-on-time */
deposit.revealedAt = uint32(block.timestamp);
deposit.vault = reveal.vault;
deposit.treasuryFee = depositTreasuryFeeDivisor > 0
? fundingOutputAmount / depositTreasuryFeeDivisor
: 0;
deposit.depositorExtraData = reveal.depositorExtraData;
}

function deposits(
uint256 depositKey
) external view returns (DepositRequest memory) {
return dep[depositKey];
}

function sweep(bytes32 fundingTxHash, uint32 fundingOutputIndex) public {
DepositRequest storage deposit = dep[
calculateDepositKey(fundingTxHash, fundingOutputIndex)
];

deposit.sweptAt = uint32(block.timestamp);

// TODO: Mint TBTC
}

function calculateDepositKey(
bytes32 fundingTxHash,
uint32 fundingOutputIndex
) public pure returns (uint256) {
return
uint256(
keccak256(abi.encodePacked(fundingTxHash, fundingOutputIndex))
);
}
}
18 changes: 18 additions & 0 deletions core/contracts/test/TBTCVaultStub.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;
import {ITBTCVault} from "../TbtcDepositor.sol";

contract TBTCVaultStub is ITBTCVault {
uint32 public optimisticMintingFeeDivisor = 500; // 1/500 = 0.002 = 0.2%

// request.optimisticMintFee = optimisticMintingFeeDivisor > 0
// ? (amountToMint / optimisticMintingFeeDivisor)
// : 0;

function optimisticMintingRequests(
uint256 depositKey
) external returns (OptimisticMintingRequest memory) {
OptimisticMintingRequest memory result;
return result;
}
}
77 changes: 77 additions & 0 deletions core/contracts/test/TbtcDepositorStub.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

import "../Acre.sol";
import "./TestERC20.sol";

// interface IBridge {
// struct BitcoinTxInfo {
// bytes4 version;
// bytes inputVector;
// bytes outputVector;
// bytes4 locktime;
// }

// struct DepositRevealInfo {
// uint32 fundingOutputIndex;
// bytes8 blindingFactor;
// bytes20 walletPubKeyHash;
// bytes20 refundPubKeyHash;
// bytes4 refundLocktime;
// address vault;
// bytes32 depositorExtraData;
// }

// function revealDepositWithExtraData(
// BitcoinTxInfo calldata fundingTx,
// DepositRevealInfo calldata reveal
// ) external;
// }

contract AcreDepositor {
// IBridge bridge;
// Acre acre;
// TestERC20 tbtc;

// struct DepositRequest {
// // UNIX timestamp at which the optimistic minting was requested.
// uint64 requestedAt;
// // UNIX timestamp at which the optimistic minting was finalized.
// // 0 if not yet finalized.
// uint64 finalizedAt;
// }

// mapping(uint256 => DepositRequest) public depositRequests;

// constructor(IBridge _bridge, Acre _acre, TestERC20 _tbtc) {
// bridge = _bridge;
// acre = _acre;
// }

// function revealDeposit(
// IBridge.BitcoinTxInfo calldata fundingTx,
// IBridge.DepositRevealInfo calldata reveal
// ) external {}

// function stake(
// bytes32 fundingTxHash,
// uint32 fundingOutputIndex,
// address receiver,
// bytes32 referral
// ) {
// // acre.stake(assets, receiver, referral);
// }

// /// @notice Calculates deposit key the same way as the Bridge contract.
// /// The deposit key is computed as
// /// `keccak256(fundingTxHash | fundingOutputIndex)`.
// function calculateDepositKey(
// bytes32 fundingTxHash,
// uint32 fundingOutputIndex
// ) public pure returns (uint256) {
// return
// uint256(
// keccak256(abi.encodePacked(fundingTxHash, fundingOutputIndex))
// );
// }
}
39 changes: 39 additions & 0 deletions core/deploy/00_resolve_tbtc_bridge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { DeployFunction } from "hardhat-deploy/types"
import type {
HardhatNetworkConfig,
HardhatRuntimeEnvironment,
} from "hardhat/types"
import { isNonZeroAddress } from "../helpers/address"

const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
const { getNamedAccounts, deployments } = hre
const { log } = deployments
const { deployer } = await getNamedAccounts()

console.log("network", hre.network.name)

const bridge = await deployments.getOrNull("Bridge")

console.log("bridge", await deployments.all())

if (bridge && isNonZeroAddress(bridge.address)) {
log(`using Bridge contract at ${bridge.address}`)
} else if (
!hre.network.tags.allowStubs ||
(hre.network.config as HardhatNetworkConfig)?.forking?.enabled
) {
throw new Error("deployed Bridge contract not found")
} else {
log("deploying Bridge contract stub")
await deployments.deploy("Bridge", {
contract: "BridgeStub",
from: deployer,
log: true,
waitConfirmations: 1,
})
}
}

export default func

func.tags = ["TBTC"]
Loading

0 comments on commit 4139748

Please sign in to comment.