Skip to content

Commit

Permalink
Merge pull request #205 from tellor-io/public-testnet-fix
Browse files Browse the repository at this point in the history
Public testnet fix
  • Loading branch information
tkernell authored Jul 12, 2024
2 parents 124b6b0 + 9afddc0 commit 8bbfdbe
Show file tree
Hide file tree
Showing 40 changed files with 1,712 additions and 194 deletions.
1 change: 0 additions & 1 deletion evm/contracts/bridge/BlobstreamO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity 0.8.22;

import "./ECDSA.sol";
import "./Constants.sol";
// import "hardhat/console.sol";

struct OracleAttestationData {
bytes32 queryId;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;

interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
interface ITellorMaster {
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function mintToOracle() external;
function totalSupply() external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
25 changes: 25 additions & 0 deletions evm/contracts/testing/TellorPlayground.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ contract TellorPlayground {
string private _name;
string private _symbol;
uint8 private _decimals;
address public oracleMintRecipient;
uint256 public lastReleaseTimeDao;

// Structs
struct StakeInfo {
Expand All @@ -60,6 +62,7 @@ contract TellorPlayground {
_symbol = "TRBP";
_decimals = 18;
token = address(this);
lastReleaseTimeDao = block.timestamp;
}

/**
Expand Down Expand Up @@ -131,6 +134,20 @@ contract TellorPlayground {
_mint(_user, 1000 ether);
}

/**
* @dev Simulates time based rewards minting
*/
function mintToOracle() external {
if (oracleMintRecipient == address(0)) {
return;
}
uint256 _releasedAmount = (146.94 ether *
(block.timestamp - lastReleaseTimeDao)) /
86400;
_mint(oracleMintRecipient, _releasedAmount);
lastReleaseTimeDao = block.timestamp;
}

/**
* @dev Allows a reporter to request to withdraw their stake
* @param _amount amount of staked tokens requesting to withdraw
Expand All @@ -147,6 +164,14 @@ contract TellorPlayground {
emit StakeWithdrawRequested(msg.sender, _amount);
}

/**
* @dev Allows the oracle mint recipient to be set for bridge testing
* @param _oracle The new oracle mint recipient
*/
function setOracleMintRecipient(address _oracle) external {
oracleMintRecipient = _oracle;
}

/**
* @dev A mock function to submit a value to be read without reporter staking needed
* @param _queryId the ID to associate the value to
Expand Down
25 changes: 0 additions & 25 deletions evm/contracts/testing/TellorUser.sol

This file was deleted.

6 changes: 3 additions & 3 deletions evm/contracts/token-bridge/LayerTransition.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity 0.8.22;

import { ITellorFlex } from "../interfaces/ITellorFlex.sol";
import { IERC20 } from "../interfaces/IERC20.sol";
import { ITellorMaster } from "../interfaces/ITellorMaster.sol";

/// @title LayerTransition.
/// @dev The contract that enables users of really old tellor to keep using it (e.g. Liquity)
Expand All @@ -11,7 +11,7 @@ import { IERC20 } from "../interfaces/IERC20.sol";
contract LayerTransition {
/*Storage*/
bytes32 updateOracleQueryId = keccak256(abi.encode("TellorOracleAddress", abi.encode(bytes(""))));
IERC20 public token;
ITellorMaster public token;
ITellorFlex public tellorFlex;

/*Functions*/
Expand All @@ -20,7 +20,7 @@ contract LayerTransition {
/// @param _token address of the tellor token (tellorMaster)
constructor(address _tellorFlex, address _token) {
tellorFlex = ITellorFlex(_tellorFlex);
token = IERC20(_token);
token = ITellorMaster(_token);
}

/// @notice this is needed because it's called when mintingToTeam. We hijack it to keep it in the bridge
Expand Down
78 changes: 42 additions & 36 deletions evm/contracts/token-bridge/TokenBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@ import { LayerTransition } from "./LayerTransition.sol";
/// Ethereum to layer. No one needs to do this. The only reason you
/// move your tokens over is to become a reporter/validator/tipper. It works by
/// using layer itself as the bridge and then reads the lightclient contract for
/// bridging back. There is a long delay in bridging back (enforced by layer) of 21 days
/// bridging back. There is a long delay in bridging back (enforced by layer) of 12 hours
contract TokenBridge is LayerTransition{
/*Storage*/
BlobstreamO public bridge;
uint256 public depositId;//counterOfHowManydeposits have been made
uint256 public depositLimitUpdateTime;//last time the limit was updated
uint256 public depositLimitRecord;//amount you can bridge per limit period
uint256 public constant DEPOSIT_LIMIT_UPDATE_INTERVAL = 12 hours;
uint256 public constant INITIAL_LAYER_TOKEN_SUPPLY = 100 ether; // update this as needed
uint256 public immutable DEPOSIT_LIMIT_DENOMINATOR = 100e18 / 20e18; // 100/depositLimitPercentage

mapping(uint256 => bool) public withdrawalClaimed;
mapping(address => uint256) public tokensToClaim;
mapping(uint256 => DepositDetails) public deposits;
mapping(uint256 => bool) public withdrawalClaimed; // withdrawal id => claimed status
mapping(address => uint256) public tokensToClaim; // recipient => extra amount to claim
mapping(uint256 => DepositDetails) public deposits; // deposit id => deposit details

struct DepositDetails {
address sender;
Expand All @@ -38,44 +37,63 @@ contract TokenBridge is LayerTransition{
/*Functions*/
/// @notice constructor
/// @param _token address of tellor token for bridging
/// @param _blobstream address of BlobstreamO for data bridge
/// @param _blobstream address of BlobstreamO data bridge
/// @param _tellorFlex address of oracle(tellorFlex) on chain
constructor(address _token, address _blobstream, address _tellorFlex) LayerTransition(_tellorFlex, _token){
bridge = BlobstreamO(_blobstream);
_refreshDepositLimit();
// _refreshDepositLimit();
}

/// @notice claim extra withdrawals that were not fully withdrawn
/// @param _recipient address of the recipient
function claimExtraWithdraw(address _recipient) external {
uint256 _amountConverted = tokensToClaim[_recipient];
require(_amountConverted > 0, "amount must be > 0");
uint256 _depositLimit = _refreshDepositLimit();
require(_depositLimit > 0, "TokenBridge: depositLimit must be > 0");
if(_depositLimit < _amountConverted){
tokensToClaim[_recipient] = tokensToClaim[_recipient] - _depositLimit;
_amountConverted = _depositLimit;
require(token.transfer(_recipient, _amountConverted), "TokenBridge: transfer failed");
}
else{
tokensToClaim[_recipient] = 0;
require(token.transfer(_recipient, _amountConverted), "TokenBridge: transfer failed");
}
depositLimitRecord -= _amountConverted;
}

/// @notice deposits tokens from Ethereum to layer
/// @param _amount amount of tokens to bridge over
/// @param _layerRecipient your cosmos address on layer (don't get it wrong!!)
function depositToLayer(uint256 _amount, string memory _layerRecipient) external {
require(_amount > 0, "TokenBridge: amount must be greater than 0");
require(token.transferFrom(msg.sender, address(this), _amount), "TokenBridge: transferFrom failed");
require(_amount <= _refreshDepositLimit(), "TokenBridge: amount exceeds deposit limit for time period");
require(token.transferFrom(msg.sender, address(this), _amount), "TokenBridge: transferFrom failed");
depositId++;
depositLimitRecord -= _amount;
deposits[depositId] = DepositDetails(msg.sender, _layerRecipient, _amount, block.number);
emit Deposit(depositId, msg.sender, _layerRecipient, _amount);
}

/// @notice This withdraws tokens from layer to mainnet Ethereum
/// @param _attest The data being verified
/// @param _attestData The data being verified
/// @param _valset array of current validator set
/// @param _sigs Signatures
/// @param _depositId depositId from the layer side
function withdrawFromLayer(
OracleAttestationData calldata _attest,
OracleAttestationData calldata _attestData,
Validator[] calldata _valset,
Signature[] calldata _sigs,
uint256 _depositId
) external {
require(_attest.queryId == keccak256(abi.encode("TRBBridge", abi.encode(false, _depositId))), "TokenBridge: invalid queryId");
require(_attestData.queryId == keccak256(abi.encode("TRBBridge", abi.encode(false, _depositId))), "TokenBridge: invalid queryId");
require(!withdrawalClaimed[_depositId], "TokenBridge: withdrawal already claimed");
require(block.timestamp - _attest.report.timestamp > 12 hours, "TokenBridge: premature attestation");
bridge.verifyOracleData(_attest, _valset, _sigs);
require(_attest.report.aggregatePower >= bridge.powerThreshold(), "Report aggregate power must be greater than or equal to _minimumPower");
require(block.timestamp - _attestData.report.timestamp > 12 hours, "TokenBridge: premature attestation");
bridge.verifyOracleData(_attestData, _valset, _sigs);
require(_attestData.report.aggregatePower >= bridge.powerThreshold(), "Report aggregate power must be greater than or equal to _minimumPower");
withdrawalClaimed[_depositId] = true;
(address _recipient, string memory _layerSender,uint256 _amountLoya) = abi.decode(_attest.report.value, (address, string, uint256));
(address _recipient, string memory _layerSender,uint256 _amountLoya) = abi.decode(_attestData.report.value, (address, string, uint256));
uint256 _amountConverted = _amountLoya * 1e12;
uint256 _depositLimit = _refreshDepositLimit();
if(_depositLimit < _amountConverted){
Expand All @@ -90,39 +108,27 @@ contract TokenBridge is LayerTransition{
emit Withdrawal(_depositId, _layerSender, _recipient, _amountConverted);
}

function claimExtraWithdraw(address _recipient) external {
uint256 _amountConverted = tokensToClaim[_recipient];
require(_amountConverted > 0, "amount must be > 0");
uint256 _depositLimit = _refreshDepositLimit();
require(_depositLimit > 0, "TokenBridge: depositLimit must be > 0");
if(_depositLimit < _amountConverted){
tokensToClaim[_recipient] = tokensToClaim[_recipient] - _depositLimit;
_amountConverted = _depositLimit;
require(token.transfer(_recipient, _amountConverted), "TokenBridge: transfer failed");
}
else{
tokensToClaim[_recipient] = 0;
require(token.transfer(_recipient, _amountConverted), "TokenBridge: transfer failed");
}
depositLimitRecord -= _amountConverted;
}

/* View Functions */
/// @notice refreshes the deposit limit every 12 hours so no one can spam layer with new tokens
function depositLimit() external view returns (uint256) {
if (block.timestamp - depositLimitUpdateTime > DEPOSIT_LIMIT_UPDATE_INTERVAL) {
uint256 _layerTokenSupply = token.balanceOf(address(this)) + INITIAL_LAYER_TOKEN_SUPPLY;
return _layerTokenSupply / DEPOSIT_LIMIT_DENOMINATOR;
return token.balanceOf(address(this)) / DEPOSIT_LIMIT_DENOMINATOR;
}
else{
return depositLimitRecord;
}
}

/* Internal Functions */
/// @notice refreshes the deposit limit every 12 hours so no one can spam layer with new tokens
function _refreshDepositLimit() internal returns (uint256) {
if (block.timestamp - depositLimitUpdateTime > DEPOSIT_LIMIT_UPDATE_INTERVAL) {
uint256 _layerTokenSupply = token.balanceOf(address(this)) + INITIAL_LAYER_TOKEN_SUPPLY;
depositLimitRecord = _layerTokenSupply / DEPOSIT_LIMIT_DENOMINATOR;
uint256 _tokenBalance = token.balanceOf(address(this));
if (_tokenBalance < 100 ether) {
token.mintToOracle();
_tokenBalance = token.balanceOf(address(this));
}
depositLimitRecord = _tokenBalance / DEPOSIT_LIMIT_DENOMINATOR;
depositLimitUpdateTime = block.timestamp;
}
return depositLimitRecord;
Expand Down
14 changes: 8 additions & 6 deletions evm/hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
//require("hardhat-gas-reporter");
require("dotenv").config();
require("@nomiclabs/hardhat-ethers");
require("hardhat-gas-reporter");

// require("@nomiclabs/hardhat-web3");

module.exports = {
Expand Down Expand Up @@ -56,16 +58,16 @@ module.exports = {
},
networks: {
hardhat: {
// accounts: {
// mnemonic:
// "nick lucian brenda kevin sam fiscal patch fly damp ocean produce wish",
// count: 40,
// },
accounts: {
mnemonic:
"nick lucian brenda kevin sam fiscal patch fly damp ocean produce wish",
count: 40,
},
forking: {
url: process.env.NODE_URL,
blockNumber: 19891853
},
// allowUnlimitedContractSize: true
allowUnlimitedContractSize: true
} //,
},
};
Expand Down
2 changes: 2 additions & 0 deletions evm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.4",
"@nomicfoundation/hardhat-network-helpers": "^1.0.10",
"@nomiclabs/hardhat-ethers": "^2.0.4",
"@nomiclabs/hardhat-web3": "^2.0.0",
"axios": "^1.6.8",
"chai": "^4.3.10",
"elliptic": "^6.5.5",
"ethers": "^5.7.0",
"hardhat": "^2.22.3",
"hardhat-gas-reporter": "^2.2.0",
"web3": "^1.10.4"
},
"mocha": {},
Expand Down
15 changes: 15 additions & 0 deletions evm/test/BlobstreamOFunctionTestsHH.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,5 +384,20 @@ describe("Blobstream - Function Tests", async function () {
currentValSetArray1,
sigStructArray1
)

// update again
newValAddrs2 = [val4.address, val5.address, val6.address, val7.address]
newPowers2 = [4, 5, 6, 7]
newThreshold2 = 15
newValHash2 = await h.calculateValHash(newValAddrs2, newPowers2)
blocky = await h.getBlock()
newValTimestamp2 = blocky.timestamp - 1
newValCheckpoint2 = h.calculateValCheckpoint(newValHash2, newThreshold2, newValTimestamp2)
sigs2 = []
for (i = 0; i < nVals; i++) {
sigs2.push(h.layerSign(newValCheckpoint2, wallets[i].privateKey))
}
sigStructArray2 = await h.getSigStructArray(sigs2)
await blobstream.updateValidatorSet(newValHash2, newThreshold2, newValTimestamp2, currentValSetArray1, sigStructArray2);
})
})
Loading

0 comments on commit 8bbfdbe

Please sign in to comment.