Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lbtc contracts #1575

Draft
wants to merge 6 commits into
base: ccip-develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions contracts/scripts/native_solc_compile_all_ccip
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,7 @@ compileContract ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol

# Customer contracts
compileContract ccip/pools/USDC/USDCTokenPool.sol
compileContract ccip/pools/LBTC/adapters/CLAdapter.sol
compileContract ccip/pools/LBTC/adapters/LombardTokenPool.sol

compileContract tests/MockV3Aggregator.sol
114 changes: 114 additions & 0 deletions contracts/src/v0.8/ccip/pools/LBTC/IBridge.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {ILBTC} from "../LBTC/ILBTC.sol";
import "./adapters/IAdapter.sol";
import {IConsortiumConsumer, INotaryConsortium} from "./IConsortiumConsumer.sol";

interface IBridge is IConsortiumConsumer {
/// @notice Emitted when the destination is unknown.
error UnknownDestination();

/// @notice Emitted when the zero address is used.
error Bridge_ZeroAddress();

error Bridge_ZeroAmount();

/// @notice Emitted adapter is not set for destination without consortium
error BadConfiguration();

/// @notice Emitted when the destination is already known.
error KnownDestination();

/// @notice Emitted when the zero contract hash is used.
error ZeroContractHash();

/// @notice Emitted when the chain id is invalid.
error ZeroChainId();

/// @notice Emitted when the destination is not valid.
error NotValidDestination();

/// @notice Emitted when amount is below commission
error AmountLessThanCommission(uint256 commission);

/// @notice Emitted when the origin contract is unknown.
error UnknownOriginContract(bytes32 fromChain, bytes32 fromContract);

/// @notice Emitted when the unexpected action is used.
error UnexpectedAction(bytes4 action);

error UnknownAdapter(address);

error PayloadAlreadyUsed(bytes32);

/// @notice Emitted no payload submitted by adapter
error AdapterNotConfirmed();

/// @notice Emitted no payload submitted by consortium
error ConsortiumNotConfirmed();

/// @notice Emitted when the deposit absolute commission is changed.
event DepositAbsoluteCommissionChanged(
uint64 newValue,
bytes32 indexed chain
);

/// @notice Emitted when the deposit relative commission is changed.
event DepositRelativeCommissionChanged(
uint16 newValue,
bytes32 indexed chain
);

/// @notice Emitted when a bridge destination is added.
event BridgeDestinationAdded(
bytes32 indexed chain,
bytes32 indexed contractAddress
);

/// @notice Emitted when a bridge destination is removed.
event BridgeDestinationRemoved(bytes32 indexed chain);

/// @notice Emitted when the adapter is changed.
event AdapterChanged(address previousAdapter, IAdapter newAdapter);

/// @notice Emitted when the is a deposit in the bridge
event DepositToBridge(
address indexed fromAddress,
bytes32 indexed toAddress,
bytes32 indexed payloadHash,
bytes payload
);

/// @notice Emitted when a withdraw is made from the bridge
event WithdrawFromBridge(
address indexed recipient,
bytes32 indexed payloadHash,
bytes payload,
uint64 amount
);

event PayloadReceived(
address indexed recipient,
bytes32 indexed payloadHash,
address indexed adapter
);

event PayloadNotarized(
address indexed recipient,
bytes32 indexed payloadHash
);

/// @notice Emitted when the treasury is changed.
event TreasuryChanged(address previousTreasury, address newTreasury);

function lbtc() external view returns (ILBTC);
function receivePayload(bytes32 fromChain, bytes calldata payload) external;
function deposit(
bytes32 toChain,
bytes32 toAddress,
uint64 amount
) external payable returns (uint256, bytes memory);
function authNotary(bytes calldata payload, bytes calldata proof) external;
function withdraw(bytes calldata payload) external returns (uint64);
}
19 changes: 19 additions & 0 deletions contracts/src/v0.8/ccip/pools/LBTC/IConsortiumConsumer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {INotaryConsortium} from "./INotaryConsortium.sol";

/**
* @title Consortium Consumer interface
* @author Lombard.Finance
* @notice Common interface for contracts who verify signatures with `INotaryConsortium`
*/
interface IConsortiumConsumer {
event ConsortiumChanged(
INotaryConsortium indexed prevVal,
INotaryConsortium indexed newVal
);

function changeConsortium(INotaryConsortium newVal) external;
function consortium() external view returns (INotaryConsortium);
}
60 changes: 60 additions & 0 deletions contracts/src/v0.8/ccip/pools/LBTC/ILBTC.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

interface ILBTC {
error ZeroAddress();
error ZeroContractHash();
error ZeroChainId();
error WithdrawalsDisabled();
error KnownDestination();
error UnknownDestination();
error ScriptPubkeyUnsupported();
error AmountLessThanCommission(uint256 fee);
error AmountBelowDustLimit(uint256 dustLimit);
error InvalidDustFeeRate();
error UnauthorizedAccount(address account);
error UnexpectedAction(bytes4 action);
error UnknownOriginContract(uint256 fromChainId, address fromContract);
error InvalidUserSignature();
error PayloadAlreadyUsed();
error InvalidInputLength();

event PauserRoleTransferred(
address indexed previousPauser,
address indexed newPauser
);
event UnstakeRequest(
address indexed fromAddress,
bytes scriptPubKey,
uint256 amount
);
event WithdrawalsEnabled(bool);
event NameAndSymbolChanged(string name, string symbol);
event ConsortiumChanged(address indexed prevVal, address indexed newVal);
event TreasuryAddressChanged(
address indexed prevValue,
address indexed newValue
);
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);
event BridgeChanged(address indexed prevVal, address indexed newVal);
event ClaimerUpdated(address indexed claimer, bool isClaimer);
event FeeCharged(uint256 indexed fee, bytes userSignature);
event FeeChanged(uint256 indexed oldFee, uint256 indexed newFee);
error FeeGreaterThanAmount();

event MintProofConsumed(
address indexed recipient,
bytes32 indexed payloadHash,
bytes payload
);

function burn(uint256 amount) external;
function burn(address from, uint256 amount) external;
function mint(address to, uint256 amount) external;
}
46 changes: 46 additions & 0 deletions contracts/src/v0.8/ccip/pools/LBTC/INotaryConsortium.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {ECDSA} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/ECDSA.sol";

interface INotaryConsortium {
/// @dev Error thrown when signature payload is already used
error PayloadAlreadyUsed();

/// @dev Error thrown when signatures length is not equal to signers length
error LengthMismatch();

/// @dev Error thrown when there are not enough signatures
error NotEnoughSignatures();

/// @dev Error thrown when ECDSA signature verification fails
error SignatureVerificationFailed(uint256 sigIndx, ECDSA.RecoverError err);

/// @dev Error thrown when signature verification fails
error WrongSignatureReceived(bytes sig);

/// @dev Error thrown when unexpected action is used
error UnexpectedAction(bytes4 action);

/// @dev Event emitted when the validator set is updated
event ValidatorSetUpdated(
uint256 indexed epoch,
address[] validators,
uint256[] weights,
uint256 threshold
);

/// @dev Error thrown when validator set already set
error ValSetAlreadySet();

/// @dev Error thrown when no validator set is set
error NoValidatorSet();

/// @dev Error thrown when invalid epoch is provided
error InvalidEpoch();

function checkProof(
bytes32 _payloadHash,
bytes calldata _proof
) external view;
}
97 changes: 97 additions & 0 deletions contracts/src/v0.8/ccip/pools/LBTC/adapters/AbstractAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {IAdapter} from "./IAdapter.sol";
import {Context} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Context.sol";
import {IBridge, ILBTC} from "../IBridge.sol";
/**
* @title Abstract bridge adapter
* @author Lombard.finance
* @notice Implements basic communication with Bridge contract.
* Should be extended with business logic of bridging protocols (e.g. CCIP, LayerZero).
*/
abstract contract AbstractAdapter is IAdapter, Context {
error Adapter_ZeroAddress();

error NotBridge();

event BridgeChanged(IBridge indexed oldBridge, IBridge indexed newBridge);

IBridge public override bridge;

constructor(IBridge bridge_) {
bridge = bridge_;
}

function lbtc() public view returns (ILBTC) {
return bridge.lbtc();
}

/// MODIFIERS ///

modifier onlyBridge() {
_onlyBridge();
_;
}

/// ONLY OWNER FUNCTIONS ///

/**
* @notice Change the bridge address
* @param bridge_ New bridge address
*/
function changeBridge(IBridge bridge_) external {
_onlyOwner();
_notZero(address(bridge_));

IBridge oldBridge = bridge;
bridge = bridge_;
emit BridgeChanged(oldBridge, bridge_);
}

/// PRIVATE FUNCTIONS ///

function _onlyOwner() internal view virtual;

function _onlyBridge() internal view {
if (_msgSender() != address(bridge)) {
revert NotBridge();
}
}

function _notZero(address addr) internal pure {
if (addr == address(0)) {
revert Adapter_ZeroAddress();
}
}

/**
* @dev Called when data is received.
*/
function _receive(bytes32 fromChain, bytes memory payload) internal {
bridge.receivePayload(fromChain, payload);
}

/**
* @notice Sends a payload from the source to destination chain.
* @param _toChain Destination chain's.
* @param _payload The payload to send.
* @param _refundAddress Address where refund fee
*/
function _deposit(
bytes32 _toChain,
bytes memory _payload,
address _refundAddress
) internal virtual {}

function deposit(
address _fromAddress,
bytes32 _toChain,
bytes32 /* _toContract */,
bytes32 /* _toAddress */,
uint256 /* _amount */,
bytes memory _payload
) external payable virtual override {
_deposit(_toChain, _payload, _fromAddress);
}
}
Loading
Loading