文件 1 的 14:DraggableShares.sol
pragma solidity ^0.8.0;
import "../recovery/ERC20Recoverable.sol";
import "../draggable/ERC20Draggable.sol";
import "../ERC20/ERC20PermitLight.sol";
contract DraggableShares is ERC20Draggable, ERC20Recoverable, ERC20PermitLight {
string public terms;
event ChangeTerms(string terms);
constructor(
string memory _terms,
IERC20 _wrappedToken,
uint256 _quorumBps,
uint256 _quorumMigration,
uint256 _votePeriodSeconds,
IRecoveryHub _recoveryHub,
IOfferFactory _offerFactory,
address _oracle
)
ERC20Draggable(_wrappedToken, _quorumBps, _quorumMigration, _votePeriodSeconds, _offerFactory, _oracle)
ERC20Recoverable(_recoveryHub)
ERC20PermitLight()
{
terms = _terms;
_recoveryHub.setRecoverable(false);
}
function transfer(address to, uint256 value) virtual override(ERC20Flaggable, ERC20Recoverable) public returns (bool) {
return super.transfer(to, value);
}
function getClaimDeleter() public view override returns (address) {
return oracle;
}
function getCollateralRate(IERC20 collateralType) public view override returns (uint256) {
uint256 rate = super.getCollateralRate(collateralType);
if (rate > 0) {
return rate;
} else {
uint256 factor = isBinding() ? 1 : unwrapConversionFactor;
if (address(collateralType) == address(wrapped)) {
return factor;
} else {
return IRecoverable(address(wrapped)).getCollateralRate(collateralType) * factor;
}
}
}
function setTerms(string calldata _terms) external override {
require(msg.sender == oracle, "not oracle");
terms = _terms;
emit ChangeTerms(terms);
}
function _beforeTokenTransfer(address from, address to, uint256 amount) virtual override(ERC20Flaggable, ERC20Draggable) internal {
super._beforeTokenTransfer(from, to, amount);
}
}
文件 2 的 14:ERC20Draggable.sol
pragma solidity ^0.8.0;
import "./IDraggable.sol";
import "../ERC20/ERC20Flaggable.sol";
import "../ERC20/IERC20.sol";
import "../ERC20/IERC677Receiver.sol";
import "./IOffer.sol";
import "./IOfferFactory.sol";
import "../shares/IShares.sol";
abstract contract ERC20Draggable is IERC677Receiver, IDraggable, ERC20Flaggable {
uint8 private constant FLAG_VOTE_HINT = 1;
IERC20 public override wrapped;
IOfferFactory public immutable factory;
uint256 public unwrapConversionFactor = 0;
IOffer public override offer;
uint256 private constant QUORUM_MULTIPLIER = 10000;
uint256 public immutable quorumMigration;
uint256 public immutable quorum;
uint256 public immutable votePeriod;
address public override oracle;
event MigrationSucceeded(address newContractAddress, uint256 yesVotes, uint256 oracleVotes, uint256 totalVotingPower);
event ChangeOracle(address oracle);
constructor(
IERC20 _wrappedToken,
uint256 _quorum,
uint256 _quorumMigration,
uint256 _votePeriod,
IOfferFactory _offerFactory,
address _oracle
)
ERC20Flaggable(0)
{
wrapped = _wrappedToken;
quorum = _quorum;
quorumMigration = _quorumMigration;
votePeriod = _votePeriod;
factory = _offerFactory;
oracle = _oracle;
}
function onTokenTransfer(
address from,
uint256 amount,
bytes calldata
) external override returns (bool) {
require(msg.sender == address(wrapped), "sender");
_mint(from, amount);
return true;
}
function wrap(address shareholder, uint256 amount) external {
require(wrapped.transferFrom(msg.sender, address(this), amount), "transfer");
_mint(shareholder, amount);
}
function isBinding() public view returns (bool) {
return unwrapConversionFactor == 0;
}
function name() public view override returns (string memory) {
string memory wrappedName = wrapped.name();
if (isBinding()) {
return string(abi.encodePacked(wrappedName, " SHA"));
} else {
return string(abi.encodePacked(wrappedName, " (Wrapped)"));
}
}
function symbol() public view override returns (string memory) {
return string(abi.encodePacked(wrapped.symbol(), "S"));
}
function deactivate(uint256 factor) internal {
require(factor >= 1, "factor");
unwrapConversionFactor = factor;
emit NameChanged(name(), symbol());
}
function unwrap(uint256 amount) external override{
require(!isBinding(), "factor");
unwrap(msg.sender, amount, unwrapConversionFactor);
}
function unwrap(address owner, uint256 amount, uint256 factor) internal {
_burn(owner, amount);
require(wrapped.transfer(owner, amount * factor), "transfer");
}
function burn(uint256 amount) external {
_burn(msg.sender, amount);
IShares(address(wrapped)).burn (isBinding() ? amount : amount * unwrapConversionFactor);
}
function makeAcquisitionOffer(
bytes32 salt,
uint256 pricePerShare,
IERC20 currency
) external payable {
require(isBinding(), "factor");
IOffer newOffer = factory.create{value: msg.value}(
salt, msg.sender, pricePerShare, currency, quorum, votePeriod);
if (offerExists()) {
offer.makeCompetingOffer(newOffer);
}
offer = newOffer;
}
function drag(address buyer, IERC20 currency) external override offerOnly {
unwrap(buyer, balanceOf(buyer), 1);
replaceWrapped(currency, buyer);
}
function notifyOfferEnded() external override offerOnly {
offer = IOffer(address(0));
}
function replaceWrapped(IERC20 newWrapped, address oldWrappedDestination) internal {
require(isBinding(), "factor");
require(wrapped.transfer(oldWrappedDestination, wrapped.balanceOf(address(this))), "transfer");
wrapped = newWrapped;
deactivate(newWrapped.balanceOf(address(this)) / totalSupply());
}
function setOracle(address newOracle) external {
require(msg.sender == oracle, "not oracle");
oracle = newOracle;
emit ChangeOracle(oracle);
}
function migrateWithExternalApproval(address successor, uint256 additionalVotes) external {
require(msg.sender == oracle, "not oracle");
require(totalSupply() + additionalVotes <= totalVotingTokens(), "votes");
migrate(successor, additionalVotes);
}
function migrate() external {
migrate(msg.sender, 0);
}
function migrate(address successor, uint256 additionalVotes) internal {
uint256 yesVotes = additionalVotes + balanceOf(successor);
uint256 totalVotes = totalVotingTokens();
require(yesVotes <= totalVotes, "votes");
require(!offerExists(), "no offer");
require(yesVotes * QUORUM_MULTIPLIER >= totalVotes * quorumMigration, "quorum");
replaceWrapped(IERC20(successor), successor);
emit MigrationSucceeded(successor, yesVotes, additionalVotes, totalVotes);
}
function votingPower(address voter) external view override returns (uint256) {
return balanceOf(voter);
}
function totalVotingTokens() public view override returns (uint256) {
return IShares(address(wrapped)).totalShares();
}
function hasVoted(address voter) internal view returns (bool) {
return hasFlagInternal(voter, FLAG_VOTE_HINT);
}
function notifyVoted(address voter) external override offerOnly {
setFlag(voter, FLAG_VOTE_HINT, true);
}
modifier offerOnly(){
require(msg.sender == address(offer), "sender");
_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
if (hasVoted(from) || hasVoted(to)) {
if (offerExists()) {
offer.notifyMoved(from, to, amount);
} else {
setFlag(from, FLAG_VOTE_HINT, false);
setFlag(to, FLAG_VOTE_HINT, false);
}
}
super._beforeTokenTransfer(from, to, amount);
}
function offerExists() internal view returns (bool) {
return address(offer) != address(0);
}
}
文件 3 的 14:ERC20Flaggable.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./IERC677Receiver.sol";
abstract contract ERC20Flaggable is IERC20 {
uint256 constant private INFINITE_ALLOWANCE = 2**255;
uint256 private constant FLAGGING_MASK = 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
uint8 public override decimals;
event NameChanged(string name, string symbol);
constructor(uint8 _decimals) {
decimals = _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return uint224 (_balances [account]);
}
function hasFlag(address account, uint8 number) external view returns (bool) {
return hasFlagInternal(account, number);
}
function setFlag(address account, uint8 index, bool value) internal {
uint256 flagMask = 1 << (index + 224);
uint256 balance = _balances [account];
if ((balance & flagMask == flagMask) != value) {
_balances [account] = balance ^ flagMask;
}
}
function hasFlagInternal(address account, uint8 number) internal view returns (bool) {
uint256 flag = 0x1 << (number + 224);
return _balances[account] & flag == flag;
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}
function allowance(address owner, address spender) external view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 value) external override returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][msg.sender];
if (currentAllowance < INFINITE_ALLOWANCE){
_allowances[sender][msg.sender] = currentAllowance - amount;
}
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
_beforeTokenTransfer(sender, recipient, amount);
decreaseBalance(sender, amount);
increaseBalance(recipient, amount);
emit Transfer(sender, recipient, amount);
}
function transferAndCall(address recipient, uint amount, bytes calldata data) external virtual returns (bool) {
return transfer (recipient, amount)
&& IERC677Receiver (recipient).onTokenTransfer (msg.sender, amount, data);
}
function _mint(address recipient, uint256 amount) internal virtual {
_beforeTokenTransfer(address(0), recipient, amount);
_totalSupply += amount;
increaseBalance(recipient, amount);
emit Transfer(address(0), recipient, amount);
}
function increaseBalance(address recipient, uint256 amount) private {
require(recipient != address(0x0), "0x0");
uint256 oldBalance = _balances[recipient];
uint256 newBalance = oldBalance + amount;
require(oldBalance & FLAGGING_MASK == newBalance & FLAGGING_MASK, "overflow");
_balances[recipient] = newBalance;
}
function _burn(address account, uint256 amount) internal virtual {
_beforeTokenTransfer(account, address(0), amount);
_totalSupply -= amount;
decreaseBalance(account, amount);
emit Transfer(account, address(0), amount);
}
function decreaseBalance(address sender, uint256 amount) private {
uint256 oldBalance = _balances[sender];
uint256 newBalance = oldBalance - amount;
require(oldBalance & FLAGGING_MASK == newBalance & FLAGGING_MASK, "underflow");
_balances[sender] = newBalance;
}
function _approve(address owner, address spender, uint256 value) internal {
_allowances[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _beforeTokenTransfer(address from, address to, uint256 amount) virtual internal {
}
}
文件 4 的 14:ERC20PermitLight.sol
pragma solidity ^0.8.0;
import "./ERC20Flaggable.sol";
import "./IERC20Permit.sol";
abstract contract ERC20PermitLight is ERC20Flaggable, IERC20Permit {
mapping(address => uint256) public override nonces;
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public override {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
bytes32(0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
_approve(recoveredAddress, spender, value);
}
}
function DOMAIN_SEPARATOR() public view override returns (bytes32) {
return
keccak256(
abi.encode(
bytes32(0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218),
block.chainid,
address(this)
)
);
}
}
文件 5 的 14:ERC20Recoverable.sol
pragma solidity ^0.8.0;
import "../ERC20/ERC20Flaggable.sol";
import "./IRecoveryHub.sol";
import "./IRecoverable.sol";
abstract contract ERC20Recoverable is ERC20Flaggable, IRecoverable {
uint8 private constant FLAG_CLAIM_PRESENT = 10;
IERC20 public customCollateralAddress;
uint256 public customCollateralRate;
uint256 constant CLAIM_PERIOD = 180 days;
IRecoveryHub public override immutable recovery;
constructor(IRecoveryHub recoveryHub){
recovery = recoveryHub;
}
function getCollateralRate(IERC20 collateralType) public override virtual view returns (uint256) {
if (address(collateralType) == address(this)) {
return 1;
} else if (collateralType == customCollateralAddress) {
return customCollateralRate;
} else {
return 0;
}
}
function claimPeriod() external pure override returns (uint256){
return CLAIM_PERIOD;
}
function _setCustomClaimCollateral(IERC20 collateral, uint256 rate) internal {
customCollateralAddress = collateral;
if (address(customCollateralAddress) == address(0)) {
customCollateralRate = 0;
} else {
require(rate > 0, "zero");
customCollateralRate = rate;
}
}
function getClaimDeleter() virtual public view returns (address);
function transfer(address recipient, uint256 amount) override(ERC20Flaggable, IERC20) virtual public returns (bool) {
require(super.transfer(recipient, amount), "transfer");
if (hasFlagInternal(msg.sender, FLAG_CLAIM_PRESENT)){
recovery.clearClaimFromToken(msg.sender);
}
return true;
}
function notifyClaimMade(address target) external override {
require(msg.sender == address(recovery), "not recovery");
setFlag(target, FLAG_CLAIM_PRESENT, true);
}
function notifyClaimDeleted(address target) external override {
require(msg.sender == address(recovery), "not recovery");
setFlag(target, FLAG_CLAIM_PRESENT, false);
}
function deleteClaim(address lostAddress) external {
require(msg.sender == getClaimDeleter(), "not claim deleter");
recovery.deleteClaim(lostAddress);
}
function recover(address oldAddress, address newAddress) external override {
require(msg.sender == address(recovery), "not recovery");
_transfer(oldAddress, newAddress, balanceOf(oldAddress));
}
}
文件 6 的 14:IDraggable.sol
pragma solidity ^0.8.0;
import "../ERC20/IERC20.sol";
import "./IOffer.sol";
interface IDraggable {
function wrapped() external view returns (IERC20);
function unwrap(uint256 amount) external;
function offer() external view returns (IOffer);
function oracle() external view returns (address);
function drag(address buyer, IERC20 currency) external;
function notifyOfferEnded() external;
function votingPower(address voter) external returns (uint256);
function totalVotingTokens() external view returns (uint256);
function notifyVoted(address voter) external;
function setTerms(string calldata _terms) external;
}
文件 7 的 14:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, 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);
}
文件 8 的 14:IERC20Permit.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
interface IERC20Permit is IERC20 {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 9 的 14:IERC677Receiver.sol
pragma solidity ^0.8.0;
interface IERC677Receiver {
function onTokenTransfer(address from, uint256 amount, bytes calldata data) external returns (bool);
}
文件 10 的 14:IOffer.sol
pragma solidity ^0.8.0;
import "../ERC20/IERC20.sol";
interface IOffer {
function makeCompetingOffer(IOffer newOffer) external;
function notifyMoved(address from, address to, uint256 value) external;
function currency() external view returns (IERC20);
function price() external view returns (uint256);
function isWellFunded() external view returns (bool);
function voteYes() external;
function voteNo() external;
}
文件 11 的 14:IOfferFactory.sol
pragma solidity ^0.8.0;
import "../ERC20/IERC20.sol";
import "./IOffer.sol";
interface IOfferFactory {
function create(
bytes32 salt, address buyer, uint256 pricePerShare, IERC20 currency, uint256 quorum, uint256 votePeriod
) external payable returns (IOffer);
}
文件 12 的 14:IRecoverable.sol
pragma solidity ^0.8.0;
import "../ERC20/IERC20.sol";
import "./IRecoveryHub.sol";
interface IRecoverable is IERC20{
function recovery() external view returns (IRecoveryHub);
function claimPeriod() external view returns (uint256);
function notifyClaimMade(address target) external;
function notifyClaimDeleted(address target) external;
function getCollateralRate(IERC20 collateral) external view returns(uint256);
function recover(address oldAddress, address newAddress) external;
}
文件 13 的 14:IRecoveryHub.sol
pragma solidity ^0.8.0;
import "./IRecoverable.sol";
interface IRecoveryHub {
function setRecoverable(bool flag) external;
function deleteClaim(address target) external;
function clearClaimFromToken(address holder) external;
function clearClaimFromUser(IRecoverable token) external;
}
文件 14 的 14:IShares.sol
pragma solidity ^0.8.0;
interface IShares {
function burn(uint256) external;
function totalShares() external view returns (uint256);
}
{
"compilationTarget": {
"src/shares/DraggableShares.sol": "DraggableShares"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"_terms","type":"string"},{"internalType":"contract IERC20","name":"_wrappedToken","type":"address"},{"internalType":"uint256","name":"_quorumBps","type":"uint256"},{"internalType":"uint256","name":"_quorumMigration","type":"uint256"},{"internalType":"uint256","name":"_votePeriodSeconds","type":"uint256"},{"internalType":"contract IRecoveryHub","name":"_recoveryHub","type":"address"},{"internalType":"contract IOfferFactory","name":"_offerFactory","type":"address"},{"internalType":"address","name":"_oracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracle","type":"address"}],"name":"ChangeOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"terms","type":"string"}],"name":"ChangeTerms","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"yesVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oracleVotes","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalVotingPower","type":"uint256"}],"name":"MigrationSucceeded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"customCollateralAddress","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"customCollateralRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lostAddress","type":"address"}],"name":"deleteClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"buyer","type":"address"},{"internalType":"contract IERC20","name":"currency","type":"address"}],"name":"drag","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IOfferFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getClaimDeleter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"collateralType","type":"address"}],"name":"getCollateralRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint8","name":"number","type":"uint8"}],"name":"hasFlag","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBinding","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"pricePerShare","type":"uint256"},{"internalType":"contract IERC20","name":"currency","type":"address"}],"name":"makeAcquisitionOffer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"successor","type":"address"},{"internalType":"uint256","name":"additionalVotes","type":"uint256"}],"name":"migrateWithExternalApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"notifyClaimDeleted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"notifyClaimMade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"notifyOfferEnded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"notifyVoted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"offer","outputs":[{"internalType":"contract IOffer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onTokenTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"quorum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quorumMigration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"oldAddress","type":"address"},{"internalType":"address","name":"newAddress","type":"address"}],"name":"recover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recovery","outputs":[{"internalType":"contract IRecoveryHub","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOracle","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_terms","type":"string"}],"name":"setTerms","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"terms","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalVotingTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"transferAndCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unwrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unwrapConversionFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"votePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"votingPower","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"shareholder","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"wrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wrapped","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]