Skip to content

Latest commit

 

History

History
772 lines (650 loc) · 22.4 KB

VestingCreator.md

File metadata and controls

772 lines (650 loc) · 22.4 KB

VestingCreator.sol

View Source: contracts/governance/Vesting/VestingCreator.sol

↗ Extends: AdminRole

VestingCreator contract

Structs

VestingData

struct VestingData {
 uint256 amount,
 uint256 cliff,
 uint256 duration,
 bool governanceControl,
 address tokenOwner,
 uint256 vestingCreationType
}

Contract Members

Constants & Variables

//internal members
bool internal vestingCreated;

//public members
uint256 public constant TWO_WEEKS;
contract IERC20 public SOV;
contract VestingRegistryLogic public vestingRegistryLogic;
struct VestingCreator.VestingData[] public vestingDataList;

Events

event SOVTransferred(address indexed receiver, uint256  amount);
event TokensStaked(address indexed vesting, address indexed tokenOwner, uint256  amount);
event VestingDataRemoved(address indexed caller, address indexed tokenOwner);
event DataCleared(address indexed caller);

Functions


constructor

function (address _SOV, address _vestingRegistryProxy) public nonpayable

Arguments

Name Type Description
_SOV address
_vestingRegistryProxy address
Source Code
constructor(address _SOV, address _vestingRegistryProxy) public {
        require(_SOV != address(0), "SOV address invalid");
        require(_vestingRegistryProxy != address(0), "Vesting registry address invalid");

        SOV = IERC20(_SOV);
        vestingRegistryLogic = VestingRegistryLogic(_vestingRegistryProxy);
    }

transferSOV

transfers SOV tokens to given address

function transferSOV(address _receiver, uint256 _amount) external nonpayable onlyOwner 

Arguments

Name Type Description
_receiver address the address of the SOV receiver
_amount uint256 the amount to be transferred
Source Code
function transferSOV(address _receiver, uint256 _amount) external onlyOwner {
        require(_amount != 0, "amount invalid");
        require(SOV.transfer(_receiver, _amount), "transfer failed");
        emit SOVTransferred(_receiver, _amount);
    }

addVestings

adds vestings to be processed to the list

function addVestings(address[] _tokenOwners, uint256[] _amounts, uint256[] _cliffs, uint256[] _durations, bool[] _governanceControls, uint256[] _vestingCreationTypes) external nonpayable onlyAuthorized 

Arguments

Name Type Description
_tokenOwners address[]
_amounts uint256[]
_cliffs uint256[]
_durations uint256[]
_governanceControls bool[]
_vestingCreationTypes uint256[]
Source Code
function addVestings(
        address[] calldata _tokenOwners,
        uint256[] calldata _amounts,
        uint256[] calldata _cliffs,
        uint256[] calldata _durations,
        bool[] calldata _governanceControls,
        uint256[] calldata _vestingCreationTypes
    ) external onlyAuthorized {
        require(
            _tokenOwners.length == _amounts.length &&
                _tokenOwners.length == _cliffs.length &&
                _tokenOwners.length == _durations.length &&
                _tokenOwners.length == _governanceControls.length,
            "arrays mismatch"
        );

        for (uint256 i = 0; i < _tokenOwners.length; i++) {
            require(
                _durations[i] >= _cliffs[i],
                "duration must be bigger than or equal to the cliff"
            );
            require(_amounts[i] > 0, "vesting amount cannot be 0");
            require(_tokenOwners[i] != address(0), "token owner cannot be 0 address");
            require(_cliffs[i].mod(TWO_WEEKS) == 0, "cliffs should have intervals of two weeks");
            require(
                _durations[i].mod(TWO_WEEKS) == 0,
                "durations should have intervals of two weeks"
            );
            VestingData memory vestingData =
                VestingData({
                    amount: _amounts[i],
                    cliff: _cliffs[i],
                    duration: _durations[i],
                    governanceControl: _governanceControls[i],
                    tokenOwner: _tokenOwners[i],
                    vestingCreationType: _vestingCreationTypes[i]
                });
            vestingDataList.push(vestingData);
        }
    }

processNextVesting

Creates vesting contract and stakes tokens

function processNextVesting() external nonpayable
Source Code
function processNextVesting() external {
        processVestingCreation();
        processStaking();
    }

processVestingCreation

Creates vesting contract without staking any tokens

function processVestingCreation() public nonpayable
Source Code
function processVestingCreation() public {
        require(!vestingCreated, "staking not done for the previous vesting");
        if (vestingDataList.length > 0) {
            VestingData storage vestingData = vestingDataList[vestingDataList.length - 1];
            _createAndGetVesting(vestingData);
            vestingCreated = true;
        }
    }

processStaking

Staking vested tokens

function processStaking() public nonpayable
Source Code
function processStaking() public {
        require(vestingCreated, "cannot stake without vesting creation");
        if (vestingDataList.length > 0) {
            VestingData storage vestingData = vestingDataList[vestingDataList.length - 1];
            address vestingAddress =
                _getVesting(
                    vestingData.tokenOwner,
                    vestingData.cliff,
                    vestingData.duration,
                    vestingData.governanceControl,
                    vestingData.vestingCreationType
                );
            if (vestingAddress != address(0)) {
                VestingLogic vesting = VestingLogic(vestingAddress);
                require(SOV.approve(address(vesting), vestingData.amount), "Approve failed");
                vesting.stakeTokens(vestingData.amount);
                emit TokensStaked(vestingAddress, vestingData.tokenOwner, vestingData.amount);
                address tokenOwnerDetails = vestingData.tokenOwner;
                vestingDataList.pop();
                emit VestingDataRemoved(msg.sender, tokenOwnerDetails);
            }
        }
        vestingCreated = false;
    }

removeNextVesting

removes next vesting data from the list

function removeNextVesting() external nonpayable onlyAuthorized 
Source Code
function removeNextVesting() external onlyAuthorized {
        address tokenOwnerDetails;
        if (vestingDataList.length > 0) {
            VestingData storage vestingData = vestingDataList[vestingDataList.length - 1];
            tokenOwnerDetails = vestingData.tokenOwner;
            vestingDataList.pop();
            emit VestingDataRemoved(msg.sender, tokenOwnerDetails);
        }
    }

clearVestingDataList

removes all data about unprocessed vestings to be processed

function clearVestingDataList() public nonpayable onlyAuthorized 
Source Code
function clearVestingDataList() public onlyAuthorized {
        delete vestingDataList;
        emit DataCleared(msg.sender);
    }

getVestingAddress

returns address after vesting creation

function getVestingAddress() external view
returns(address)
Source Code
function getVestingAddress() external view returns (address) {
        return
            _getVesting(
                vestingDataList[vestingDataList.length - 1].tokenOwner,
                vestingDataList[vestingDataList.length - 1].cliff,
                vestingDataList[vestingDataList.length - 1].duration,
                vestingDataList[vestingDataList.length - 1].governanceControl,
                vestingDataList[vestingDataList.length - 1].vestingCreationType
            );
    }

getVestingPeriod

returns period i.e. ((duration - cliff) / 4 WEEKS)

function getVestingPeriod() external view
returns(uint256)
Source Code
function getVestingPeriod() external view returns (uint256) {
        uint256 duration = vestingDataList[vestingDataList.length - 1].duration;
        uint256 cliff = vestingDataList[vestingDataList.length - 1].cliff;
        uint256 fourWeeks = TWO_WEEKS.mul(2);
        uint256 period = duration.sub(cliff).div(fourWeeks);
        return period;
    }

getUnprocessedCount

returns count of vestings to be processed

function getUnprocessedCount() external view
returns(uint256)
Source Code
function getUnprocessedCount() external view returns (uint256) {
        return vestingDataList.length;
    }

getUnprocessedAmount

returns total amount of vestings to be processed

function getUnprocessedAmount() public view
returns(uint256)
Source Code
function getUnprocessedAmount() public view returns (uint256) {
        uint256 amount = 0;
        uint256 length = vestingDataList.length;
        for (uint256 i = 0; i < length; i++) {
            amount = amount.add(vestingDataList[i].amount);
        }
        return amount;
    }

isEnoughBalance

checks if contract balance is enough to process all vestings

function isEnoughBalance() public view
returns(bool)
Source Code
function isEnoughBalance() public view returns (bool) {
        return SOV.balanceOf(address(this)) >= getUnprocessedAmount();
    }

getMissingBalance

returns missed balance to process all vestings

function getMissingBalance() external view
returns(uint256)
Source Code
function getMissingBalance() external view returns (uint256) {
        if (isEnoughBalance()) {
            return 0;
        }
        return getUnprocessedAmount() - SOV.balanceOf(address(this));
    }

_createAndGetVesting

creates TeamVesting or Vesting contract

function _createAndGetVesting(struct VestingCreator.VestingData vestingData) internal nonpayable
returns(vesting address)

Arguments

Name Type Description
vestingData struct VestingCreator.VestingData
Source Code
function _createAndGetVesting(VestingData memory vestingData)
        internal
        returns (address vesting)
    {
        if (vestingData.governanceControl) {
            vestingRegistryLogic.createTeamVesting(
                vestingData.tokenOwner,
                vestingData.amount,
                vestingData.cliff,
                vestingData.duration,
                vestingData.vestingCreationType
            );
        } else {
            vestingRegistryLogic.createVestingAddr(
                vestingData.tokenOwner,
                vestingData.amount,
                vestingData.cliff,
                vestingData.duration,
                vestingData.vestingCreationType
            );
        }
        return
            _getVesting(
                vestingData.tokenOwner,
                vestingData.cliff,
                vestingData.duration,
                vestingData.governanceControl,
                vestingData.vestingCreationType
            );
    }

_getVesting

returns an address of TeamVesting or Vesting contract (depends on a governance control)

function _getVesting(address _tokenOwner, uint256 _cliff, uint256 _duration, bool _governanceControl, uint256 _vestingCreationType) internal view
returns(vestingAddress address)

Arguments

Name Type Description
_tokenOwner address
_cliff uint256
_duration uint256
_governanceControl bool
_vestingCreationType uint256
Source Code
function _getVesting(
        address _tokenOwner,
        uint256 _cliff,
        uint256 _duration,
        bool _governanceControl,
        uint256 _vestingCreationType
    ) internal view returns (address vestingAddress) {
        if (_governanceControl) {
            vestingAddress = vestingRegistryLogic.getTeamVesting(
                _tokenOwner,
                _cliff,
                _duration,
                _vestingCreationType
            );
        } else {
            vestingAddress = vestingRegistryLogic.getVestingAddr(
                _tokenOwner,
                _cliff,
                _duration,
                _vestingCreationType
            );
        }
    }

Contracts