Contract Address Details

0x6f04fAC9B248ADCC773FFE878E330CeA5B191541

Contract Name
Referral
Creator
0x069994–523777 at 0x214ce9–c8c141
Balance
0.00 NRG
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
2473493
Contract name:
Referral




Optimization enabled
true
Compiler version
v0.5.16+commit.9c3226ce




Optimization runs
200
EVM Version
istanbul




Verified at
2021-10-22 16:53:20.855576Z

Constructor Arguments

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000305000000000000000000000000335adfaa6e499ddeb066efb6d2753ec1baa521de

Arg [0] (address) : 0x0000000000000000000000000000000000000000
Arg [1] (address) : 0x0000000000000000000000000000000000000305
Arg [2] (address) : 0x335adfaa6e499ddeb066efb6d2753ec1baa521de

              

Contract source code

pragma solidity 0.5.16;
// File: ../interfaces/IGovernedContract.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
/**
* Genesis version of GovernedContract interface.
*
* Base Consensus interface for upgradable contracts.
* Unlike common approach, the implementation is NOT expected to be
* called through delegatecall() to minimize risks of shared storage.
*
* NOTE: it MUST NOT change after blockchain launch!
*/
interface IGovernedContract {
// Return actual proxy address for secure validation
function proxy() external view returns (address);
// It must check that the caller is the proxy
// and copy all required data from the old address.
function migrate(IGovernedContract _oldImpl) external;
// It must check that the caller is the proxy
// and self destruct to the new address.
function destroy(IGovernedContract _newImpl) external;
// function () external payable; // This line (from original Energi IGovernedContract) is commented because it
// makes truffle migrations fail
}
// File: ../StorageBase.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
/**
* Base for contract storage (SC-14).
*
* NOTE: it MUST NOT change after blockchain launch!
*/
contract StorageBase {
address payable internal owner;
modifier requireOwner {
require(msg.sender == address(owner), "StorageBase: Not owner!");
_;
}
constructor() public {
owner = msg.sender;
}
function setOwner(IGovernedContract _newOwner) external requireOwner {
owner = address(uint160(address(_newOwner)));
}
function kill() external requireOwner {
selfdestruct(msg.sender);
}
}
// File: ../GovernedContract.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
/**
* Genesis version of GovernedContract common base.
*
* Base Consensus interface for upgradable contracts.
* Unlike common approach, the implementation is NOT expected to be
* called through delegatecall() to minimize risks of shared storage.
*
* NOTE: it MUST NOT change after blockchain launch!
*/
contract GovernedContract is IGovernedContract {
address public proxy;
constructor(address _proxy) public {
proxy = _proxy;
}
modifier requireProxy {
require(msg.sender == proxy, "Governed Contract: Not proxy");
_;
}
function getProxy() internal view returns (address _proxy) {
_proxy = proxy;
}
// Function overridden in child contract
function migrate(IGovernedContract _oldImpl) external requireProxy {
_migrate(_oldImpl);
}
// Function overridden in child contract
function destroy(IGovernedContract _newImpl) external requireProxy {
_destroy(_newImpl);
}
// solium-disable-next-line no-empty-blocks
function _migrate(IGovernedContract) internal {}
function _destroy(IGovernedContract _newImpl) internal {
selfdestruct(address(uint160(address(_newImpl))));
}
function _callerAddress() internal view returns (address payable) {
if (msg.sender == proxy) {
// This is guarantee of the GovernedProxy
// solium-disable-next-line security/no-tx-origin
return tx.origin;
} else {
return msg.sender;
}
}
}
// File: ../NonReentrant.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
/**
* A little helper to protect contract from being re-entrant in state
* modifying functions.
*/
contract NonReentrant {
uint256 private entry_guard;
modifier noReentry {
require(entry_guard == 0, "NonReentrant: Reentry");
entry_guard = 1;
_;
entry_guard = 0;
}
}
// File: ../interfaces/IProposal.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
interface IProposal {
function parent() external view returns (address);
function created_block() external view returns (uint256);
function deadline() external view returns (uint256);
function fee_payer() external view returns (address payable);
function fee_amount() external view returns (uint256);
function accepted_weight() external view returns (uint256);
function rejected_weight() external view returns (uint256);
function total_weight() external view returns (uint256);
function quorum_weight() external view returns (uint256);
function isFinished() external view returns (bool);
function isAccepted() external view returns (bool);
function withdraw() external;
function destroy() external;
function collect() external;
function voteAccept() external;
function voteReject() external;
function setFee() external payable;
function canVote(address owner) external view returns (bool);
}
// File: ../interfaces/IUpgradeProposal.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
/**
* Interface of UpgradeProposal
*/
contract IUpgradeProposal is IProposal {
function impl() external view returns (IGovernedContract);
}
// File: ../interfaces/IGovernedProxy.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
//pragma experimental SMTChecker;
/**
* Genesis version of IGovernedProxy interface.
*
* Base Consensus interface for upgradable contracts proxy.
* Unlike common approach, the implementation is NOT expected to be
* called through delegatecall() to minimize risks of shared storage.
*
* NOTE: it MUST NOT change after blockchain launch!
*/
interface IGovernedProxy {
event UpgradeProposal(
IGovernedContract indexed impl,
IUpgradeProposal proposal
);
event Upgraded(IGovernedContract indexed impl, IUpgradeProposal proposal);
function impl() external view returns (IGovernedContract);
function spork_proxy() external view returns (IGovernedProxy);
function proposeUpgrade(IGovernedContract _newImpl, uint256 _period)
external
payable
returns (IUpgradeProposal);
function upgrade(IUpgradeProposal _proposal) external;
function upgradeProposalImpl(IUpgradeProposal _proposal)
external
view
returns (IGovernedContract new_impl);
function listUpgradeProposals()
external
view
returns (IUpgradeProposal[] memory proposals);
function collectUpgradeProposal(IUpgradeProposal _proposal) external;
function() external payable;
}
// File: ../interfaces/ISporkRegistry.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
interface ISporkRegistry {
function createUpgradeProposal(
IGovernedContract _impl,
uint256 _period,
address payable _fee_payer
) external payable returns (IUpgradeProposal);
function consensusGasLimits()
external
view
returns (uint256 callGas, uint256 xferGas);
}
// File: ReferralGovernedProxy.sol
// Copyright 2021 The Energi Core Authors
// This file is part of Energi Core.
//
// Energi Core is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Energi Core is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Energi Core. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
/**
* SC-9: This contract has no chance of being updated. It must be stupid simple.
*
* If another upgrade logic is required in the future - it can be done as proxy stage II.
*/
contract ReferralGovernedProxy is
NonReentrant,
IGovernedContract,
IGovernedProxy
{
modifier senderOrigin {
// Internal calls are expected to use impl directly.
// That's due to use of call() instead of delegatecall() on purpose.
// solium-disable-next-line security/no-tx-origin
require(
tx.origin == msg.sender,
"ReferralGovernedProxy: Only direct calls are allowed!"
);
_;
}
modifier onlyImpl {
require(
msg.sender == address(impl),
"ReferralGovernedProxy: Only calls from impl are allowed!"
);
_;
}
IGovernedContract public impl;
IGovernedProxy public spork_proxy;
mapping(address => IGovernedContract) public upgrade_proposals;
IUpgradeProposal[] public upgrade_proposal_list;
constructor(address payable _sporkProxy, address _impl) public {
spork_proxy = IGovernedProxy(_sporkProxy);
impl = IGovernedContract(_impl);
}
event Referral(address indexed referrer, address indexed referee);
function emitReferral(address referrer, address referee) external onlyImpl {
emit Referral(referrer, referee);
}
/**
* Pre-create a new contract first.
* Then propose upgrade based on that.
*/
function proposeUpgrade(IGovernedContract _newImpl, uint256 _period)
external
payable
senderOrigin
noReentry
returns (IUpgradeProposal)
{
require(
_newImpl != impl,
"ReferralGovernedProxy: Already active!"
);
require(
_newImpl.proxy() == address(this),
"ReferralGovernedProxy: Wrong proxy!"
);
ISporkRegistry spork_reg = ISporkRegistry(address(spork_proxy.impl()));
IUpgradeProposal proposal =
spork_reg.createUpgradeProposal.value(msg.value)(
_newImpl,
_period,
msg.sender
);
upgrade_proposals[address(proposal)] = _newImpl;
upgrade_proposal_list.push(proposal);
emit UpgradeProposal(_newImpl, proposal);
return proposal;
}
/**
* Once proposal is accepted, anyone can activate that.
*/
function upgrade(IUpgradeProposal _proposal) external noReentry {
IGovernedContract new_impl = upgrade_proposals[address(_proposal)];
require(
new_impl != impl,
"ReferralGovernedProxy: Already active!"
);
// in case it changes in the flight
require(
address(new_impl) != address(0),
"ReferralGovernedProxy: Not registered!"
);
require(
_proposal.isAccepted(),
"ReferralGovernedProxy: Not accepted!"
);
IGovernedContract old_impl = impl;
new_impl.migrate(old_impl);
impl = new_impl;
old_impl.destroy(new_impl);
// SECURITY: prevent downgrade attack
_cleanupProposal(_proposal);
// Return fee ASAP
_proposal.destroy();
emit Upgraded(new_impl, _proposal);
}
/**
* Map proposal to implementation
*/
function upgradeProposalImpl(IUpgradeProposal _proposal)
external
view
returns (IGovernedContract new_impl)
{
new_impl = upgrade_proposals[address(_proposal)];
}
/**
* Lists all available upgrades
*/
function listUpgradeProposals()
external
view
returns (IUpgradeProposal[] memory proposals)
{
uint256 len = upgrade_proposal_list.length;
proposals = new IUpgradeProposal[](len);
for (uint256 i = 0; i < len; ++i) {
proposals[i] = upgrade_proposal_list[i];
}
return proposals;
}
/**
* Once proposal is reject, anyone can start collect procedure.
*/
function collectUpgradeProposal(IUpgradeProposal _proposal)
external
noReentry
{
IGovernedContract new_impl = upgrade_proposals[address(_proposal)];
require(
address(new_impl) != address(0),
"ReferralGovernedProxy: Not registered!"
);
_proposal.collect();
delete upgrade_proposals[address(_proposal)];
_cleanupProposal(_proposal);
}
function _cleanupProposal(IUpgradeProposal _proposal) internal {
delete upgrade_proposals[address(_proposal)];
uint256 len = upgrade_proposal_list.length;
for (uint256 i = 0; i < len; ++i) {
if (upgrade_proposal_list[i] == _proposal) {
upgrade_proposal_list[i] = upgrade_proposal_list[len - 1];
upgrade_proposal_list.pop();
break;
}
}
}
/**
* Related to above
*/
function proxy() external view returns (address) {
return address(this);
}
/**
* SECURITY: prevent on-behalf-of calls
*/
function migrate(IGovernedContract) external {
revert("ReferralGovernedProxy: Good try");
}
/**
* SECURITY: prevent on-behalf-of calls
*/
function destroy(IGovernedContract) external {
revert("ReferralGovernedProxy: Good try");
}
/**
* Proxy all other calls to implementation.
*/
function() external payable senderOrigin {
// SECURITY: senderOrigin() modifier is mandatory
IGovernedContract impl_m = impl;
// solium-disable-next-line security/no-inline-assembly
assembly {
let ptr := mload(0x40)
calldatacopy(ptr, 0, calldatasize)
let res := call(sub(gas, 10000), impl_m, callvalue, ptr, calldatasize, 0, 0)
// NOTE: returndatasize should allow repeatable calls
// what should save one opcode.
returndatacopy(ptr, 0, returndatasize)
switch res
case 0 {
revert(ptr, returndatasize)
}
default {
return(ptr, returndatasize)
}
}
}
}
// File: ReferralAutoProxy.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
/**
* ReferralAutoProxy is a version of GovernedContract which deploys its own proxy.
* This is useful to avoid a circular dependency between GovernedContract and GovernedProxy
* wherein they need each other's address in the constructor.
* If you want a new governed contract to create a proxy, pass address(0) when deploying
* otherwise, you can pass a proxy address like in normal GovernedContract
*/
contract ReferralAutoProxy is GovernedContract {
constructor(address _proxy, address payable _sporkProxy, address _impl) public GovernedContract(_proxy) {
if (_proxy == address(0)) {
_proxy = address(new ReferralGovernedProxy(_sporkProxy, _impl));
}
proxy = _proxy;
}
}
// File: IReferralGovernedProxy.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
interface IReferralGovernedProxy {
event Referral(address indexed referrer, address indexed referee);
function emitReferral(address referrer, address referee) external;
}
// File: ../interfaces/IStorageBase.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
interface IStorageBase {
function setOwner(address _newOwner) external;
}
// File: ../interfaces/IWhitelist.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
interface IWhitelist {
function isWhitelisted(address _item) external view returns (bool);
}
// File: Referral.sol
// Copyright 2021 Energi Core
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Energi Governance system is the fundamental part of Energi Core.
// NOTE: It's not allowed to change the compiler due to byte-to-byte
// match requirement.
contract ReferralStorage is StorageBase {
uint256 private count = 0;
// A referrer can have many referees
mapping(address => address[]) private referees; // referrer => referees[]
mapping(address => uint256) private refereesCount; // referrer => refereesCount
mapping(address => address) private referrer; // referee => referrer
function setReferral(address _referrer, address _referee) external requireOwner {
referees[_referrer].push(_referee);
referrer[_referee] = _referrer;
refereesCount[_referrer] += 1;
count += 1;
}
function getCount() external view returns (uint256 _count) {
_count = count;
}
function getReferrer(address _referee) external view returns (address _referrer) {
_referrer = referrer[_referee];
}
function getReferees(address _referrer, uint256 _offset, uint256 _count) external view returns (address[] memory _referees) {
// Offset should be smaller than referees array length
require(_offset < referees[_referrer].length, "Referral: offset too large");
// Adjust count if needed
if (_offset + _count >= referees[_referrer].length) {
_count = referees[_referrer].length - _offset;
}
// Return specified subset of referees array
_referees = new address[](_count);
for (uint256 i = 0; i < _count; i++) {
uint256 index = _offset + i;
_referees[i] = referees[_referrer][index];
}
}
function getRefereesCount(address _referrer) external view returns (uint256 _refereesCount) {
_refereesCount = refereesCount[_referrer];
}
}
contract Referral is ReferralAutoProxy {
ReferralStorage public _storage;
address public whitelistProxyAddress;
modifier requireWhitelisted {
require(msg.sender == proxy || IWhitelist(getWhitelistImpl()).isWhitelisted(msg.sender), "Referral: FORBIDDEN, not whitelisted");
_;
}
function getWhitelistImpl() private view returns(address _whitelist) {
_whitelist = address(IGovernedProxy(address(uint160(whitelistProxyAddress))).impl());
}
function getSender() private view returns(address _sender){
// Determine sender to allow whitelisted contracts to interact
// If msg.sender is a whitelisted contract, this contract is the sender
// Else, tx.origin is the sender
_sender = IWhitelist(getWhitelistImpl()).isWhitelisted(msg.sender) ? msg.sender : tx.origin;
}
constructor(
address _proxy,
address payable _sporkProxy,
address _whitelistProxyAddress
) public ReferralAutoProxy(_proxy, _sporkProxy, address(this)) {
whitelistProxyAddress = _whitelistProxyAddress;
_storage = new ReferralStorage();
}
// This function is called in order to upgrade to a new Referral implementation
function destroy(IGovernedContract _newImpl) external requireProxy {
IStorageBase(address(_storage)).setOwner(address(_newImpl));
// Self destruct
_destroy(_newImpl);
}
// This function (placeholder) would be called on the new implementation if necessary for the upgrade
function migrate(IGovernedContract _oldImpl) external requireProxy {
_migrate(_oldImpl);
}
function refereesCount(address _referrer) external view returns (uint256) {
return _storage.getRefereesCount(_referrer);
}
function allRefereesCount() external view returns (uint256) {
return _storage.getCount();
}
function referrer(address _referee) external view returns (address) {
return _storage.getReferrer(_referee);
}
function referees(address _referrer, uint256 _offset, uint256 _count) external view returns (address[] memory) {
return _storage.getReferees(_referrer, _offset, _count);
}
function setReferral(address _referrer) external requireWhitelisted {
// Get referee address
address referee = getSender();
// User cannot refer self
require(referee != _referrer, "Referral: cannot refer self");
// Referee can only be referred once
require(_storage.getReferrer(referee) == address(0), "Referral: already referred");
// Register referral in storage
_storage.setReferral(_referrer, referee);
// Emit referral event
IReferralGovernedProxy(proxy).emitReferral(_referrer, referee);
}
}

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[{"type":"address","name":"_proxy","internalType":"address"},{"type":"address","name":"_sporkProxy","internalType":"address payable"},{"type":"address","name":"_whitelistProxyAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contract ReferralStorage"}],"name":"_storage","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allRefereesCount","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"destroy","inputs":[{"type":"address","name":"_newImpl","internalType":"contract IGovernedContract"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"migrate","inputs":[{"type":"address","name":"_oldImpl","internalType":"contract IGovernedContract"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"proxy","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"referees","inputs":[{"type":"address","name":"_referrer","internalType":"address"},{"type":"uint256","name":"_offset","internalType":"uint256"},{"type":"uint256","name":"_count","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"refereesCount","inputs":[{"type":"address","name":"_referrer","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"referrer","inputs":[{"type":"address","name":"_referee","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setReferral","inputs":[{"type":"address","name":"_referrer","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"whitelistProxyAddress","inputs":[],"constant":true}]
            

Deployed ByteCode

0x608060405234801561001057600080fd5b506004361061009c5760003560e01c80639e5914da116100665780639e5914da146101af578063c3fb90d6146101d5578063ce5494bb146101dd578063e32ef3c514610203578063ec556889146102295761009c565b806289add4146100a1578062f55d9d146100c5578063271ec4b2146100ed5780632cf003c2146101075780636a01553c1461012d575b600080fd5b6100a9610231565b604080516001600160a01b039092168252519081900360200190f35b6100eb600480360360208110156100db57600080fd5b50356001600160a01b0316610240565b005b6100f5610311565b60408051918252519081900360200190f35b6100a96004803603602081101561011d57600080fd5b50356001600160a01b0316610387565b61015f6004803603606081101561014357600080fd5b506001600160a01b03813516906020810135906040013561040a565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561019b578181015183820152602001610183565b505050509050019250505060405180910390f35b6100eb600480360360208110156101c557600080fd5b50356001600160a01b031661053b565b6100a961083b565b6100eb600480360360208110156101f357600080fd5b50356001600160a01b031661084a565b6100f56004803603602081101561021957600080fd5b50356001600160a01b03166108b2565b6100a9610903565b6002546001600160a01b031681565b6000546001600160a01b0316331461029f576040805162461bcd60e51b815260206004820152601c60248201527f476f7665726e656420436f6e74726163743a204e6f742070726f787900000000604482015290519081900360640190fd5b600154604080516313af403560e01b81526001600160a01b038481166004830152915191909216916313af403591602480830192600092919082900301818387803b1580156102ed57600080fd5b505af1158015610301573d6000803e3d6000fd5b5050505061030e81610912565b50565b60015460408051632a1f650b60e21b815290516000926001600160a01b03169163a87d942c916004808301926020929190829003018186803b15801561035657600080fd5b505afa15801561036a573d6000803e3d6000fd5b505050506040513d602081101561038057600080fd5b5051905090565b60015460408051634a9fefc760e01b81526001600160a01b03848116600483015291516000939290921691634a9fefc791602480820192602092909190829003018186803b1580156103d857600080fd5b505afa1580156103ec573d6000803e3d6000fd5b505050506040513d602081101561040257600080fd5b505192915050565b600154604080516365d9ab3160e01b81526001600160a01b0386811660048301526024820186905260448201859052915160609392909216916365d9ab3191606480820192600092909190829003018186803b15801561046957600080fd5b505afa15801561047d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156104a657600080fd5b81019080805160405193929190846401000000008211156104c657600080fd5b9083019060208201858111156104db57600080fd5b82518660208202830111640100000000821117156104f857600080fd5b82525081516020918201928201910280838360005b8381101561052557818101518382015260200161050d565b5050505090500160405250505090509392505050565b6000546001600160a01b03163314806105d9575061055761091e565b6001600160a01b0316633af32abf336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156105ac57600080fd5b505afa1580156105c0573d6000803e3d6000fd5b505050506040513d60208110156105d657600080fd5b50515b6106145760405162461bcd60e51b8152600401808060200182810382526024815260200180610a006024913960400191505060405180910390fd5b600061061e610963565b9050816001600160a01b0316816001600160a01b03161415610687576040805162461bcd60e51b815260206004820152601b60248201527f526566657272616c3a2063616e6e6f742072656665722073656c660000000000604482015290519081900360640190fd5b60015460408051634a9fefc760e01b81526001600160a01b038481166004830152915160009390921691634a9fefc791602480820192602092909190829003018186803b1580156106d757600080fd5b505afa1580156106eb573d6000803e3d6000fd5b505050506040513d602081101561070157600080fd5b50516001600160a01b03161461075e576040805162461bcd60e51b815260206004820152601a60248201527f526566657272616c3a20616c7265616479207265666572726564000000000000604482015290519081900360640190fd5b600154604080516307543e3f60e41b81526001600160a01b038581166004830152848116602483015291519190921691637543e3f091604480830192600092919082900301818387803b1580156107b457600080fd5b505af11580156107c8573d6000803e3d6000fd5b50506000805460408051630e5a07a160e31b81526001600160a01b038881166004830152878116602483015291519190921694506372d03d0893506044808301939282900301818387803b15801561081f57600080fd5b505af1158015610833573d6000803e3d6000fd5b505050505050565b6001546001600160a01b031681565b6000546001600160a01b031633146108a9576040805162461bcd60e51b815260206004820152601c60248201527f476f7665726e656420436f6e74726163743a204e6f742070726f787900000000604482015290519081900360640190fd5b61030e8161030e565b60015460408051636a7a8a4b60e11b81526001600160a01b0384811660048301529151600093929092169163d4f5149691602480820192602092909190829003018186803b1580156103d857600080fd5b6000546001600160a01b031681565b806001600160a01b0316ff5b60025460408051638abf607760e01b815290516000926001600160a01b031691638abf6077916004808301926020929190829003018186803b15801561035657600080fd5b600061096d61091e565b6001600160a01b0316633af32abf336040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156109c257600080fd5b505afa1580156109d6573d6000803e3d6000fd5b505050506040513d60208110156109ec57600080fd5b50516109f857326109fa565b335b90509056fe526566657272616c3a20464f5242494444454e2c206e6f742077686974656c6973746564a265627a7a72315820d2287946f83fcc8f33e7bc470777401b99c920e6bcb4f389511466d2ee5d3b8b64736f6c63430005100032