Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Use specific contract types #542

Merged
merged 13 commits into from
Mar 26, 2020
6 changes: 3 additions & 3 deletions solidity/contracts/DepositLog.sol
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ contract DepositLog {
/// @notice Sets the tbtcDepositToken contract.
/// @dev The contract is used by `approvedToLog` to check if the
/// caller is a Deposit contract. This should only be called once.
/// @param _tbtcDepositTokenAddress The address of the tbtcDepositToken.
function setTbtcDepositToken(address _tbtcDepositTokenAddress) public {
/// @param _tbtcDepositToken tbtcDepositToken contract.
function setTbtcDepositToken(TBTCDepositToken _tbtcDepositToken) public {
require(
address(tbtcDepositToken) == address(0),
"tbtcDepositToken is already set"
);
tbtcDepositToken = TBTCDepositToken(_tbtcDepositTokenAddress);
tbtcDepositToken = _tbtcDepositToken;
}

//
Expand Down
35 changes: 20 additions & 15 deletions solidity/contracts/deposit/Deposit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import {DepositUtils} from "./DepositUtils.sol";
import {DepositFunding} from "./DepositFunding.sol";
import {DepositRedemption} from "./DepositRedemption.sol";
import {DepositStates} from "./DepositStates.sol";
import {ITBTCSystem} from "../interfaces/ITBTCSystem.sol";
import {IERC721} from "openzeppelin-solidity/contracts/token/ERC721/IERC721.sol";
import {TBTCToken} from "../system/TBTCToken.sol";
import {FeeRebateToken} from "../system/FeeRebateToken.sol";

import "../system/DepositFactoryAuthority.sol";

/// @title Deposit.
Expand Down Expand Up @@ -92,32 +97,32 @@ contract Deposit is DepositFactoryAuthority {
// THIS IS THE INIT FUNCTION
/// @notice The Deposit Factory can spin up a new deposit.
/// @dev Only the Deposit factory can call this.
/// @param _TBTCSystem `TBTCSystem` address. More info in `VendingMachine`.
/// @param _TBTCToken `TBTCToken` address. More info in TBTCToken`.
/// @param _TBTCDepositToken `TBTCDepositToken` (TDT) address. More info in `TBTCDepositToken`.
/// @param _FeeRebateToken `FeeRebateToken` (FRT) address. More info in `FeeRebateToken`.
/// @param _VendingMachine `VendingMachine` address. More info in `VendingMachine`.
/// @param _TBTCSystem `TBTCSystem` contract. More info in `VendingMachine`.
/// @param _TBTCToken `TBTCToken` contract. More info in TBTCToken`.
/// @param _TBTCDepositToken `TBTCDepositToken` (TDT) contract. More info in `TBTCDepositToken`.
/// @param _FeeRebateToken `FeeRebateToken` (FRT) contract. More info in `FeeRebateToken`.
/// @param _VendingMachineAddress `VendingMachine` address. More info in `VendingMachine`.
/// @param _m Signing group honesty threshold.
/// @param _n Signing group size.
/// @param _lotSizeSatoshis The minimum amount of satoshi the funder is required to send.
/// This is also the amount of TBTC the TDT holder will receive:
/// (10**7 satoshi == 0.1 BTC == 0.1 TBTC).
/// @return True if successful, otherwise revert.
function createNewDeposit(
address _TBTCSystem,
address _TBTCToken,
address _TBTCDepositToken,
address _FeeRebateToken,
address _VendingMachine,
ITBTCSystem _TBTCSystem,
TBTCToken _TBTCToken,
IERC721 _TBTCDepositToken,
FeeRebateToken _FeeRebateToken,
address _VendingMachineAddress,
uint256 _m,
uint256 _n,
uint256 _lotSizeSatoshis
) public onlyFactory payable returns (bool) {
self.TBTCSystem = _TBTCSystem;
self.TBTCToken = _TBTCToken;
self.TBTCDepositToken = _TBTCDepositToken;
self.FeeRebateToken = _FeeRebateToken;
self.VendingMachine = _VendingMachine;
self.tbtcSystem = _TBTCSystem;
self.tbtcToken = _TBTCToken;
self.tbtcDepositToken = _TBTCDepositToken;
self.feeRebateToken = _FeeRebateToken;
self.VendingMachineAddress = _VendingMachineAddress;
Shadowfiend marked this conversation as resolved.
Show resolved Hide resolved
self.createNewDeposit(_m, _n, _lotSizeSatoshis);
return true;
}
Expand Down
19 changes: 8 additions & 11 deletions solidity/contracts/deposit/DepositFunding.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {BytesLib} from "@summa-tx/bitcoin-spv-sol/contracts/BytesLib.sol";
import {BTCUtils} from "@summa-tx/bitcoin-spv-sol/contracts/BTCUtils.sol";
import {IBondedECDSAKeep} from "@keep-network/keep-ecdsa/contracts/api/IBondedECDSAKeep.sol";
import {TBTCToken} from "../system/TBTCToken.sol";
import {TBTCSystem} from "../system/TBTCSystem.sol";
import {DepositUtils} from "./DepositUtils.sol";
import {DepositLiquidation} from "./DepositLiquidation.sol";
import {DepositStates} from "./DepositStates.sol";
Expand Down Expand Up @@ -55,22 +54,20 @@ library DepositFunding {
uint256 _n,
uint256 _lotSizeSatoshis
) public returns (bool) {
TBTCSystem _system = TBTCSystem(_d.TBTCSystem);

require(_system.getAllowNewDeposits(), "Opening new deposits is currently disabled.");
require(_d.tbtcSystem.getAllowNewDeposits(), "Opening new deposits is currently disabled.");
require(_d.inStart(), "Deposit setup already requested");
require(_system.isAllowedLotSize(_lotSizeSatoshis), "provided lot size not supported");
require(_d.tbtcSystem.isAllowedLotSize(_lotSizeSatoshis), "provided lot size not supported");

_d.lotSizeSatoshis = _lotSizeSatoshis;
uint256 _bondRequirementSatoshi = _lotSizeSatoshis.mul(_system.getInitialCollateralizedPercent()).div(100);
uint256 _bondRequirementSatoshi = _lotSizeSatoshis.mul(_d.tbtcSystem.getInitialCollateralizedPercent()).div(100);
uint256 _bondRequirementWei = _d.fetchBitcoinPrice().mul(_bondRequirementSatoshi);

/* solium-disable-next-line value-in-payable */
_d.keepAddress = _system.requestNewKeep.value(msg.value)(_m, _n, _bondRequirementWei);
_d.signerFeeDivisor = _system.getSignerFeeDivisor();
_d.undercollateralizedThresholdPercent = _system.getUndercollateralizedThresholdPercent();
_d.severelyUndercollateralizedThresholdPercent = _system.getSeverelyUndercollateralizedThresholdPercent();
_d.initialCollateralizedPercent = _system.getInitialCollateralizedPercent();
_d.keepAddress = _d.tbtcSystem.requestNewKeep.value(msg.value)(_m, _n, _bondRequirementWei);
_d.signerFeeDivisor = _d.tbtcSystem.getSignerFeeDivisor();
_d.undercollateralizedThresholdPercent = _d.tbtcSystem.getUndercollateralizedThresholdPercent();
_d.severelyUndercollateralizedThresholdPercent = _d.tbtcSystem.getSeverelyUndercollateralizedThresholdPercent();
_d.initialCollateralizedPercent = _d.tbtcSystem.getInitialCollateralizedPercent();
_d.signingGroupRequestedAt = block.timestamp;

_d.setAwaitingSignerSetup();
Expand Down
10 changes: 4 additions & 6 deletions solidity/contracts/deposit/DepositLiquidation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,14 @@ library DepositLiquidation {
// send the TBTC to the TDT holder. If the TDT holder is the Vending Machine, burn it to maintain the peg.
address tdtHolder = _d.depositOwner();

TBTCToken _tbtcToken = TBTCToken(_d.TBTCToken);

uint256 lotSizeTbtc = _d.lotSizeTbtc();
require(_tbtcToken.balanceOf(msg.sender) >= lotSizeTbtc, "Not enough TBTC to cover outstanding debt");
require(_d.tbtcToken.balanceOf(msg.sender) >= lotSizeTbtc, "Not enough TBTC to cover outstanding debt");

if(tdtHolder == _d.VendingMachine){
_tbtcToken.burnFrom(msg.sender, lotSizeTbtc); // burn minimal amount to cover size
if(tdtHolder == _d.VendingMachineAddress){
_d.tbtcToken.burnFrom(msg.sender, lotSizeTbtc); // burn minimal amount to cover size
}
else{
_tbtcToken.transferFrom(msg.sender, tdtHolder, lotSizeTbtc);
_d.tbtcToken.transferFrom(msg.sender, tdtHolder, lotSizeTbtc);
}

// Distribute funds to auction buyer
Expand Down
28 changes: 11 additions & 17 deletions solidity/contracts/deposit/DepositRedemption.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,10 @@ library DepositRedemption {
/// @notice Pushes signer fee to the Keep group by transferring it to the Keep address.
/// @dev Approves the keep contract, then expects it to call transferFrom.
function distributeSignerFee(DepositUtils.Deposit storage _d) internal {
address _tbtcTokenAddress = _d.TBTCToken;
TBTCToken _tbtcToken = TBTCToken(_tbtcTokenAddress);

IBondedECDSAKeep _keep = IBondedECDSAKeep(_d.keepAddress);

_tbtcToken.approve(_d.keepAddress, _d.signerFee());
_keep.distributeERC20Reward(_tbtcTokenAddress, _d.signerFee());
_d.tbtcToken.approve(_d.keepAddress, _d.signerFee());
_keep.distributeERC20Reward(_d.tbtcToken, _d.signerFee());
}

/// @notice Closes keep associated with the deposit.
Expand All @@ -61,9 +58,8 @@ library DepositRedemption {
/// @notice Handles TBTC requirements for redemption.
/// @dev Burns or transfers depending on term and supply-peg impact.
function performRedemptionTBTCTransfers(DepositUtils.Deposit storage _d) internal {
TBTCToken _tbtc = TBTCToken(_d.TBTCToken);
address tdtHolder = _d.depositOwner();
address vendingMachine = _d.VendingMachine;
address vendingMachineAddress = _d.VendingMachineAddress;

uint256 tbtcLot = _d.lotSizeTbtc();
uint256 signerFee = _d.signerFee();
Expand All @@ -75,7 +71,7 @@ library DepositRedemption {
}
// if we owe > 0 & < signerfee, msg.sender is TDT owner but not FRT holder.
if(tbtcOwed <= signerFee){
_tbtc.transferFrom(msg.sender, address(this), tbtcOwed);
_d.tbtcToken.transferFrom(msg.sender, address(this), tbtcOwed);
return;
}
// Redemmer always owes a full TBTC for at-term redemption.
Expand All @@ -85,17 +81,17 @@ library DepositRedemption {
// As compensation, the TDT owner is reimbursed in TBTC
// Vending Machine-owned TDTs have been used to mint TBTC,
// and we should always burn a full TBTC to redeem the deposit.
if(tdtHolder == vendingMachine){
_tbtc.burnFrom(msg.sender, tbtcLot);
if(tdtHolder == vendingMachineAddress){
_d.tbtcToken.burnFrom(msg.sender, tbtcLot);
}
// if signer fee is not escrowed, escrow and it here and send the rest to TDT owner
else if(_tbtc.balanceOf(address(this)) < signerFee){
_tbtc.transferFrom(msg.sender, address(this), signerFee);
_tbtc.transferFrom(msg.sender, tdtHolder, tbtcLot.sub(signerFee));
else if(_d.tbtcToken.balanceOf(address(this)) < signerFee){
_d.tbtcToken.transferFrom(msg.sender, address(this), signerFee);
_d.tbtcToken.transferFrom(msg.sender, tdtHolder, tbtcLot.sub(signerFee));
}
// tansfer a full TBTC to TDT owner if signerFee is escrowed
else{
_tbtc.transferFrom(msg.sender, tdtHolder, tbtcLot);
_d.tbtcToken.transferFrom(msg.sender, tdtHolder, tbtcLot);
}
return;
}
Expand Down Expand Up @@ -162,9 +158,7 @@ library DepositRedemption {
bytes memory _redeemerOutputScript,
address payable _finalRecipient
) public {
IERC721 _tbtcDepositToken = IERC721(_d.TBTCDepositToken);

_tbtcDepositToken.transferFrom(msg.sender, _finalRecipient, uint256(address(this)));
_d.tbtcDepositToken.transferFrom(msg.sender, _finalRecipient, uint256(address(this)));

_requestRedemption(_d, _outputValueBytes, _redeemerOutputScript, _finalRecipient);
}
Expand Down
35 changes: 14 additions & 21 deletions solidity/contracts/deposit/DepositUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ library DepositUtils {
struct Deposit {

// SET DURING CONSTRUCTION
address TBTCSystem;
address TBTCToken;
address TBTCDepositToken;
address FeeRebateToken;
address VendingMachine;
ITBTCSystem tbtcSystem;
TBTCToken tbtcToken;
IERC721 tbtcDepositToken;
FeeRebateToken feeRebateToken;
address VendingMachineAddress;
uint256 lotSizeSatoshis;
uint8 currentState;
uint256 signerFeeDivisor;
Expand Down Expand Up @@ -74,16 +74,14 @@ library DepositUtils {
/// @dev Calls the light relay and gets the current block difficulty.
/// @return The difficulty.
function currentBlockDifficulty(Deposit storage _d) public view returns (uint256) {
ITBTCSystem _sys = ITBTCSystem(_d.TBTCSystem);
return _sys.fetchRelayCurrentDifficulty();
return _d.tbtcSystem.fetchRelayCurrentDifficulty();
}

/// @notice Gets the previous block difficulty.
/// @dev Calls the light relay and gets the previous block difficulty.
/// @return The difficulty.
function previousBlockDifficulty(Deposit storage _d) public view returns (uint256) {
ITBTCSystem _sys = ITBTCSystem(_d.TBTCSystem);
return _sys.fetchRelayPreviousDifficulty();
return _d.tbtcSystem.fetchRelayPreviousDifficulty();
}

/// @notice Evaluates the header difficulties in a proof.
Expand Down Expand Up @@ -310,8 +308,7 @@ library DepositUtils {
/// @dev Polls the price feed via the system contract.
/// @return The current price of 1 sat in wei.
function fetchBitcoinPrice(Deposit storage _d) public view returns (uint256) {
ITBTCSystem _sys = ITBTCSystem(_d.TBTCSystem);
return _sys.fetchBitcoinPrice();
return _d.tbtcSystem.fetchBitcoinPrice();
}

/// @notice Fetches the Keep's bond amount in wei.
Expand Down Expand Up @@ -342,10 +339,9 @@ library DepositUtils {
/// @return The current token holder if the Token exists.
/// address(0) if the token does not exist.
function feeRebateTokenHolder(Deposit storage _d) public view returns (address payable) {
FeeRebateToken _feeRebateToken = FeeRebateToken(_d.FeeRebateToken);
address tokenHolder;
if(_feeRebateToken.exists(uint256(address(this)))){
tokenHolder = address(uint160(_feeRebateToken.ownerOf(uint256(address(this)))));
if(_d.feeRebateToken.exists(uint256(address(this)))){
tokenHolder = address(uint160(_d.feeRebateToken.ownerOf(uint256(address(this)))));
}
return address(uint160(tokenHolder));
}
Expand All @@ -354,8 +350,7 @@ library DepositUtils {
/// @dev We cast the address to a uint256 to match the 721 standard.
/// @return The current deposit beneficiary.
function depositOwner(Deposit storage _d) public view returns (address payable) {
IERC721 _tbtcDepositToken = IERC721(_d.TBTCDepositToken);
return address(uint160(_tbtcDepositToken.ownerOf(uint256(address(this)))));
return address(uint160(_d.tbtcDepositToken.ownerOf(uint256(address(this)))));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there room here for an overload of ownerAddressOf that takes a Deposit and returns an address and does all of the weird type conversions for us as needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that might be a good idea.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not worth cycles unless you're motivated, but yeah, seems cleaner.

}

/// @notice Deletes state after termination of redemption process.
Expand Down Expand Up @@ -394,16 +389,14 @@ library DepositUtils {
/// @notice Distributes the fee rebate to the Fee Rebate Token owner.
/// @dev Whenever this is called we are shutting down.
function distributeFeeRebate(Deposit storage _d) internal {
TBTCToken _tbtc = TBTCToken(_d.TBTCToken);

address rebateTokenHolder = feeRebateTokenHolder(_d);

// We didn't escrow a rebate if the redeemer is also the Fee Rebate Token holder
if(_d.redeemerAddress == rebateTokenHolder) return;

// pay out the rebate if it is available
if(_tbtc.balanceOf(address(this)) >= signerFee(_d)) {
_tbtc.transfer(rebateTokenHolder, signerFee(_d));
if(_d.tbtcToken.balanceOf(address(this)) >= signerFee(_d)) {
_d.tbtcToken.transfer(rebateTokenHolder, signerFee(_d));
}
}

Expand All @@ -430,7 +423,7 @@ library DepositUtils {
return fee;
}
}
uint256 contractTbtcBalance = TBTCToken(_d.TBTCToken).balanceOf(address(this));
uint256 contractTbtcBalance = _d.tbtcToken.balanceOf(address(this));
if(contractTbtcBalance < fee) {
return fee.sub(contractTbtcBalance);
}
Expand Down
Loading