Skip to content
This repository was archived by the owner on Aug 22, 2023. It is now read-only.
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
[submodule "lib/solmate"]
path = lib/solmate
url = https://github.com/transmissions11/solmate
[submodule "lib/chain-abstraction-integration"]
path = lib/chain-abstraction-integration
url = https://github.com/connext/chain-abstraction-integration
16 changes: 16 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"overrides": [
{
"files": ["*.sol", "*.ts", "*.tsx", ".js"],
"options": {
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": true,
"explicitTypes": "always",
"trailingComma": "none"
}
}
]
}
61 changes: 33 additions & 28 deletions contracts/VoteEscrow.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import {IERC721, IERC721Metadata} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import {IVotes} from "@openzeppelin/contracts/governance/utils/IVotes.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import { IVotesUpgradeable } from "@openzeppelin/contracts-upgradeable/governance/utils/IVotesUpgradeable.sol";

import {IERC20} from "./interfaces/IERC20.sol";
import {IVoteEscrow} from "./interfaces/IVoteEscrow.sol";
import {XERC721Upgradeable} from "./XERC721Upgradeable.sol";

/// @title Voting Escrow
/// @notice veNFT implementation that escrows ERC-20 tokens in the form of an ERC-721 NFT
Expand All @@ -18,8 +18,7 @@ import {IVoteEscrow} from "./interfaces/IVoteEscrow.sol";
/// @author Modified from THENA (https://github.com/ThenafiBNB/THENA-Contracts/blob/main/contracts/VotingEscrow.sol)
/// @dev Vote weight decays linearly over time. Lock time cannot be more than `MAXTIME` (1 years).

// TODO XERC20Upgradeable
contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradeable {
contract VoteEscrow is XERC721Upgradeable, IVotesUpgradeable, ReentrancyGuardUpgradeable {
enum DepositType {
DEPOSIT_FOR_TYPE,
CREATE_LOCK_TYPE,
Expand Down Expand Up @@ -92,7 +91,6 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea

uint256 public masterChainId;
uint128 constant ARBITRUM_ONE = 42161;
address public bridge;
address public auctionsFactory;

modifier onlyOnMasterChain() {
Expand All @@ -104,11 +102,20 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
_disableInitializers();
}

function initialize(address token_addr, address _bridge, address _auctionsFactory) external initializer {
function initialize(string memory name_, string memory symbol_) external initializer {
__ERC721_init(name_, symbol_);
}

function initialize(address token_addr, address _auctionsFactory) external initializer {
__ReentrancyGuard_init();
__Ownable_init();
__Ownable2Step_init();
__ERC721_init("veIonic", "veION");
__XERC721_init();

_transferOwnership(msg.sender);

masterChainId = ARBITRUM_ONE;
bridge = _bridge;
auctionsFactory = _auctionsFactory;
token = token_addr;
voter = msg.sender;
Expand All @@ -131,10 +138,10 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
METADATA STORAGE
------------------------------------------------------------*/

string constant public name = "veIonic";
string constant public symbol = "veION";
string constant public version = "1.0.0";
uint8 constant public decimals = 18;
// string constant public name = "veIonic";
// string constant public symbol = ;
string constant public version = "1.0.0";
// uint8 constant public decimals = 18;

function setTeam(address _team) external {
require(msg.sender == team);
Expand All @@ -143,7 +150,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea

/// @dev Returns current token URI metadata
/// @param _tokenId Token ID to fetch URI for.
function tokenURI(uint _tokenId) external view returns (string memory) {
function tokenURI(uint _tokenId) public view override returns (string memory) {
require(idToOwner[_tokenId] != address(0), "Query for nonexistent token");
LockedBalance memory _locked = locked[_tokenId];
// return IVeArtProxy(artProxy)._tokenURI(_tokenId,_balanceOfNFT(_tokenId, block.timestamp),_locked.end,uint(int256(_locked.amount)));
Expand All @@ -161,7 +168,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea

/// @dev Returns the address of the owner of the NFT.
/// @param _tokenId The identifier for an NFT.
function ownerOf(uint _tokenId) public view returns (address) {
function ownerOf(uint _tokenId) public view override returns (address) {
return idToOwner[_tokenId];
}

Expand All @@ -175,7 +182,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
/// @dev Returns the number of NFTs owned by `_owner`.
/// Throws if `_owner` is the zero address. NFTs assigned to the zero address are considered invalid.
/// @param _owner Address for whom to query the balance.
function balanceOf(address _owner) external view returns (uint) {
function balanceOf(address _owner) public view override returns (uint) {
return _balance(_owner);
}

Expand All @@ -193,14 +200,14 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea

/// @dev Get the approved address for a single NFT.
/// @param _tokenId ID of the NFT to query the approval of.
function getApproved(uint _tokenId) external view returns (address) {
function getApproved(uint _tokenId) public view override returns (address) {
return idToApprovals[_tokenId];
}

/// @dev Checks if `_operator` is an approved operator for `_owner`.
/// @param _owner The address that owns the NFTs.
/// @param _operator The address that acts on behalf of the owner.
function isApprovedForAll(address _owner, address _operator) external view returns (bool) {
function isApprovedForAll(address _owner, address _operator) public view override returns (bool) {
return (ownerToOperators[_owner])[_operator];
}

Expand All @@ -214,7 +221,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
/// Throws if `_approved` is the current owner. (NOTE: This is not written the EIP)
/// @param _approved Address to be approved for the given NFT ID.
/// @param _tokenId ID of the token to be approved.
function approve(address _approved, uint _tokenId) public {
function approve(address _approved, uint _tokenId) public override {
address owner = idToOwner[_tokenId];
// Throws if `_tokenId` is not a valid NFT
require(owner != address(0));
Expand All @@ -235,7 +242,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
/// @notice This works even if sender doesn't own any tokens at the time.
/// @param _operator Address to add to the set of authorized operators.
/// @param _approved True if the operators is approved, false to revoke approval.
function setApprovalForAll(address _operator, bool _approved) external {
function setApprovalForAll(address _operator, bool _approved) public override {
// Throws if `_operator` is the `msg.sender`
assert(_operator != msg.sender);
ownerToOperators[msg.sender][_operator] = _approved;
Expand All @@ -258,7 +265,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
/// @param _spender address of the spender to query
/// @param _tokenId uint ID of the token to be transferred
/// @return bool whether the msg.sender is approved for the given token ID, is an operator of the owner, or is the owner of the token
function _isApprovedOrOwner(address _spender, uint _tokenId) internal view returns (bool) {
function _isApprovedOrOwner(address _spender, uint _tokenId) internal view override returns (bool) {
address owner = idToOwner[_tokenId];
bool spenderIsOwner = owner == _spender;
bool spenderIsApproved = _spender == idToApprovals[_tokenId];
Expand Down Expand Up @@ -313,7 +320,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
address _from,
address _to,
uint _tokenId
) external {
) public override {
_transferFrom(_from, _to, _tokenId, msg.sender);
}

Expand All @@ -332,7 +339,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
address _from,
address _to,
uint _tokenId
) external {
) public override {
safeTransferFrom(_from, _to, _tokenId, "");
}

Expand Down Expand Up @@ -364,7 +371,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
address _to,
uint _tokenId,
bytes memory _data
) public {
) public override {
_transferFrom(_from, _to, _tokenId, msg.sender);

if (_isContract(_to)) {
Expand All @@ -391,7 +398,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea

/// @dev Interface identification is specified in ERC-165.
/// @param _interfaceID Id of the interface
function supportsInterface(bytes4 _interfaceID) external view returns (bool) {
function supportsInterface(bytes4 _interfaceID) public view override returns (bool) {
return supportedInterfaces[_interfaceID];
}

Expand Down Expand Up @@ -438,16 +445,14 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
/// Throws if `_tokenId` is owned by someone.
/// @param _to The address that will receive the minted tokens.
/// @param _tokenId The token id to mint.
/// @return A boolean that indicates if the operation was successful.
function _mint(address _to, uint _tokenId) internal returns (bool) {
function _mint(address _to, uint _tokenId) internal override {
// Throws if `_to` is zero address
assert(_to != address(0));
// checkpoint for gov
_moveTokenDelegates(address(0), delegates(_to), _tokenId);
// Add NFT. Throws if `_tokenId` is owned by someone
_addTokenTo(_to, _tokenId);
emit Transfer(address(0), _to, _tokenId);
return true;
}

/// @dev Remove a NFT from an index mapping to a given address
Expand Down Expand Up @@ -493,7 +498,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
ownerToNFTokenCount[_from] -= 1;
}

function _burn(uint _tokenId) internal {
function _burn(uint _tokenId) internal override {
require(_isApprovedOrOwner(msg.sender, _tokenId), "caller is not owner nor approved");

address owner = ownerOf(_tokenId);
Expand Down Expand Up @@ -1398,7 +1403,7 @@ contract VoteEscrow is IERC721, IERC721Metadata, IVotes, ReentrancyGuardUpgradea
bytes32 domainSeparator = keccak256(
abi.encode(
DOMAIN_TYPEHASH,
keccak256(bytes(name)),
keccak256(bytes(name())),
keccak256(bytes(version)),
block.chainid,
address(this)
Expand Down
67 changes: 67 additions & 0 deletions contracts/XERC721Upgradeable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import { IERC721Upgradeable, IERC721MetadataUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol";
import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";

abstract contract XERC721Upgradeable is ERC721Upgradeable, Ownable2StepUpgradeable {
event BridgeAdded(address indexed bridge);
event BridgeRemoved(address indexed bridge);

mapping(address => bool) internal _whitelistedBridges;

constructor() {}

function initialize(address _owner, string memory _name, string memory _symbol) public initializer {
__Ownable_init();
__Ownable2Step_init();
__ERC721_init(_name, _symbol);
__XERC721_init();

_transferOwnership(_owner);
}

function __XERC721_init() internal onlyInitializing {
__XERC721_init_unchained();
}

function __XERC721_init_unchained() internal onlyInitializing {}

error XERC721__onlyBridge_notBridge();
error XERC721__addBridge_alreadyAdded();
error XERC721__removeBridge_alreadyRemoved();

modifier onlyBridge() {
if (!_whitelistedBridges[msg.sender]) {
revert XERC721__onlyBridge_notBridge();
}
_;
}

function addBridge(address _bridge) external onlyOwner {
if (_whitelistedBridges[_bridge]) {
revert XERC721__addBridge_alreadyAdded();
}
emit BridgeAdded(_bridge);
_whitelistedBridges[_bridge] = true;
}

function removeBridge(address _bridge) external onlyOwner {
if (!_whitelistedBridges[_bridge]) {
revert XERC721__removeBridge_alreadyRemoved();
}
emit BridgeRemoved(_bridge);
_whitelistedBridges[_bridge] = false;
}

function mint(address _to, uint256 _tokenId) public onlyBridge {
_mint(_to, _tokenId);
}

function burn(uint256 _tokenId) public onlyBridge {
_burn(_tokenId);
}

uint256[49] private __GAP; // gap for upgrade safety
}
1 change: 1 addition & 0 deletions lib/chain-abstraction-integration
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,17 @@
"mocha": "^9.2.2",
"solidity-coverage": "^0.7.20",
"ts-node": "^10.9.1"
},
"scripts": {
"forge": "forge",
"prettier": "prettier --write --plugin=prettier-plugin-solidity 'contracts/**/*.sol' --config .prettierrc",
"lint": "prettier --list-different 'contracts/**/*.sol'"
},
"files": [
"contracts"
],
"devDependencies": {
"prettier": "^2.6.2",
"prettier-plugin-solidity": "^1.0.0-beta.19"
}
}
25 changes: 23 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,13 @@
dependencies:
antlr4ts "^0.5.0-alpha.4"

"@solidity-parser/parser@^0.16.0":
version "0.16.1"
resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.1.tgz#f7c8a686974e1536da0105466c4db6727311253c"
integrity sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==
dependencies:
antlr4ts "^0.5.0-alpha.4"

"@szmarczak/http-timer@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
Expand Down Expand Up @@ -7953,7 +7960,16 @@ prepend-http@^2.0.0:
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==

prettier@^2.1.2:
prettier-plugin-solidity@^1.0.0-beta.19:
version "1.1.3"
resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.3.tgz#9a35124f578404caf617634a8cab80862d726cba"
integrity sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg==
dependencies:
"@solidity-parser/parser" "^0.16.0"
semver "^7.3.8"
solidity-comments-extractor "^0.0.7"

prettier@^2.1.2, prettier@^2.6.2:
version "2.8.8"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
Expand Down Expand Up @@ -8682,7 +8698,7 @@ semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==

semver@^7.3.4:
semver@^7.3.4, semver@^7.3.8:
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
Expand Down Expand Up @@ -8967,6 +8983,11 @@ solidity-ast@^0.4.15:
resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.49.tgz#ecba89d10c0067845b7848c3a3e8cc61a4fc5b82"
integrity sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ==

solidity-comments-extractor@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19"
integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==

solidity-coverage@^0.7.20:
version "0.7.22"
resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.7.22.tgz#168f414be4c0f5303addcf3ab9714cf64f72c080"
Expand Down