Skip to content

Commit

Permalink
Merge pull request #15 from lombard-finance/dev
Browse files Browse the repository at this point in the history
Release BTCBPMM
  • Loading branch information
hashxtree authored Oct 2, 2024
2 parents ef000df + 1defc13 commit 1bb0292
Show file tree
Hide file tree
Showing 27 changed files with 2,353 additions and 846 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/hardhat-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Hardhat Tests

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: [self-hosted]

steps:
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "18.17.0"

- name: Cache node modules
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Run Hardhat tests
run: yarn hardhat test
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ yarn hardhat test
```
#### Deploy
```bash
yarn hardhat run deploy-consortium.ts
yarn hardhat run deploy-timelock.ts
yarn hardhat run deploy-lbtc.ts
yarn hardhat deploy-consortium [params]
yarn hardhat deploy-timelock [params]
yarn hardhat deploy-lbtc [params]
```
1 change: 1 addition & 0 deletions contracts/LBTC/ILBTC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ interface ILBTC {
event BurnCommissionChanged(uint64 indexed prevValue, uint64 indexed newValue);
event DustFeeRateChanged(uint256 indexed oldRate, uint256 indexed newRate);
event BasculeChanged(address indexed prevVal, address indexed newVal);
event MinterUpdated(address indexed minter, bool isMinter);
}
46 changes: 45 additions & 1 deletion contracts/LBTC/LBTC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {ERC20Upgradeable, IERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {ERC20PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol";
import {ERC20PermitUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";
import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import { BitcoinUtils, OutputType } from "../libs/BitcoinUtils.sol";
Expand All @@ -21,7 +22,7 @@ import "../libs/EIP1271SignatureUtils.sol";
* @author Lombard.Finance
* @notice The contracts is a part of Lombard.Finace protocol
*/
contract LBTC is ILBTC, ERC20PausableUpgradeable, Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {
contract LBTC is ILBTC, ERC20PausableUpgradeable, Ownable2StepUpgradeable, ReentrancyGuardUpgradeable, ERC20PermitUpgradeable {

/// @custom:storage-location erc7201:lombardfinance.storage.LBTC
struct LBTCStorage {
Expand Down Expand Up @@ -58,6 +59,8 @@ contract LBTC is ILBTC, ERC20PausableUpgradeable, Ownable2StepUpgradeable, Reent
IBascule bascule;

address pauser;

mapping(address => bool) minters;
}

// keccak256(abi.encode(uint256(keccak256("lombardfinance.storage.LBTC")) - 1)) & ~bytes32(uint256(0xff))
Expand Down Expand Up @@ -98,6 +101,10 @@ contract LBTC is ILBTC, ERC20PausableUpgradeable, Ownable2StepUpgradeable, Reent
emit DustFeeRateChanged(0, $.dustFeeRate);
}

function reinitialize() external reinitializer(2) {
__ERC20Permit_init("Lombard Staked Bitcoin");
}

function toggleWithdrawals() external onlyOwner {
LBTCStorage storage $ = _getLBTCStorage();
$.isWithdrawalsEnabled = !$.isWithdrawalsEnabled;
Expand Down Expand Up @@ -128,6 +135,16 @@ contract LBTC is ILBTC, ERC20PausableUpgradeable, Ownable2StepUpgradeable, Reent
$.consortium = newVal;
}

/// @notice Mint LBTC to the specified address
/// @param amount The amount of LBTC to mint
/// @dev Only callable by whitelisted minters
function mint(address to, uint256 amount) external {
if(!_getLBTCStorage().minters[_msgSender()])
revert UnauthorizedAccount(_msgSender());

_mint(to, amount);
}

function mint(
bytes calldata data,
bytes calldata proofSignature
Expand Down Expand Up @@ -603,4 +620,31 @@ contract LBTC is ILBTC, ERC20PausableUpgradeable, Ownable2StepUpgradeable, Reent
$.pauser = newPauser;
emit PauserRoleTransferred(oldPauser, newPauser);
}

function addMinter(address newMinter) external onlyOwner {
_updateMinter(newMinter, true);
}

function removeMinter(address oldMinter) external onlyOwner {
_updateMinter(oldMinter, false);
}

function isMinter(address minter) external view returns (bool) {
return _getLBTCStorage().minters[minter];
}

function _updateMinter(address minter, bool _isMinter) internal {
if (minter == address(0)) {
revert ZeroAddress();
}
_getLBTCStorage().minters[minter] = _isMinter;
emit MinterUpdated(minter, _isMinter);
}

/**
* @dev Override of the _update function to satisfy both ERC20Upgradeable and ERC20PausableUpgradeable
*/
function _update(address from, address to, uint256 value) internal virtual override(ERC20Upgradeable, ERC20PausableUpgradeable) {
super._update(from, to, value);
}
}
166 changes: 166 additions & 0 deletions contracts/consortium/ILombardTimelockController.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (governance/TimelockController.sol)

pragma solidity 0.8.24;

interface ITimelockController {
/**
* @dev Returns whether an id corresponds to a registered operation. This
* includes both Waiting, Ready, and Done operations.
*/
function isOperation(bytes32 id) external view returns (bool);

/**
* @dev Returns whether an operation is pending or not. Note that a "pending" operation may also be "ready".
*/
function isOperationPending(bytes32 id) external view returns (bool);

/**
* @dev Returns whether an operation is ready for execution. Note that a "ready" operation is also "pending".
*/
function isOperationReady(bytes32 id) external view returns (bool);

/**
* @dev Returns whether an operation is done or not.
*/
function isOperationDone(bytes32 id) external view returns (bool);

/**
* @dev Returns the timestamp at which an operation becomes ready (0 for
* unset operations, 1 for done operations).
*/
function getTimestamp(bytes32 id) external view returns (uint256);

/**
* @dev Returns operation state.
*/
// function getOperationState(bytes32 id) public view virtual returns (OperationState);

/**
* @dev Returns the minimum delay in seconds for an operation to become valid.
*
* This value can be changed by executing an operation that calls `updateDelay`.
*/
function getMinDelay() external view returns (uint256);

/**
* @dev Returns the identifier of an operation containing a single
* transaction.
*/
function hashOperation(
address target,
uint256 value,
bytes calldata data,
bytes32 predecessor,
bytes32 salt
) external pure returns (bytes32);

/**
* @dev Returns the identifier of an operation containing a batch of
* transactions.
*/
function hashOperationBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt
) external pure returns (bytes32);

/**
* @dev Schedule an operation containing a single transaction.
*
* Emits {CallSalt} if salt is nonzero, and {CallScheduled}.
*
* Requirements:
*
* - the caller must have the 'proposer' role.
*/
function schedule(
address target,
uint256 value,
bytes calldata data,
bytes32 predecessor,
bytes32 salt,
uint256 delay
) external;

/**
* @dev Schedule an operation containing a batch of transactions.
*
* Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.
*
* Requirements:
*
* - the caller must have the 'proposer' role.
*/
function scheduleBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt,
uint256 delay
) external;

/**
* @dev Cancel an operation.
*
* Requirements:
*
* - the caller must have the 'canceller' role.
*/
function cancel(bytes32 id) external;

/**
* @dev Execute an (ready) operation containing a single transaction.
*
* Emits a {CallExecuted} event.
*
* Requirements:
*
* - the caller must have the 'executor' role.
*/
// This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
// thus any modifications to the operation during reentrancy should be caught.
// slither-disable-next-line reentrancy-eth
function execute(
address target,
uint256 value,
bytes calldata payload,
bytes32 predecessor,
bytes32 salt
) external;

/**
* @dev Execute an (ready) operation containing a batch of transactions.
*
* Emits one {CallExecuted} event per transaction in the batch.
*
* Requirements:
*
* - the caller must have the 'executor' role.
*/
// This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
// thus any modifications to the operation during reentrancy should be caught.
// slither-disable-next-line reentrancy-eth
function executeBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt
) external payable;

/**
* @dev Changes the minimum timelock duration for future operations.
*
* Emits a {MinDelayChange} event.
*
* Requirements:
*
* - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
* an operation where the timelock is the target and the data is the ABI-encoded call to this function.
*/
function updateDelay(uint256 newDelay) external;
}
31 changes: 31 additions & 0 deletions contracts/libs/IProxyAdmin.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/ProxyAdmin.sol)

pragma solidity 0.8.24;

interface IProxyAdmin {
/**
* @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgrade(address)`
* and `upgradeAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
* while `upgradeAndCall` will invoke the `receive` function if the second argument is the empty byte string.
* If the getter returns `"5.0.0"`, only `upgradeAndCall(address,bytes)` is present, and the second argument must
* be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
* during an upgrade.
*/
function UPGRADE_INTERFACE_VERSION() external returns (string memory);

/**
* @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation.
* See {TransparentUpgradeableProxy-_dispatchUpgradeToAndCall}.
*
* Requirements:
*
* - This contract must be the admin of `proxy`.
* - If `data` is empty, `msg.value` must be zero.
*/
function upgradeAndCall(
address proxy,
address implementation,
bytes memory data
) external payable;
}
Loading

0 comments on commit 1bb0292

Please sign in to comment.