ETH Price: $2,592.54 (+0.31%)

Transaction Decoder

Block:
10643271 at Aug-12-2020 05:41:55 AM +UTC
Transaction Fee:
0.3086774 ETH $800.26
Gas Used:
1,543,387 Gas / 200 Gwei

Emitted Events:

123 Swapper.PrimaryTransferred( recipient=[Sender] 0xf3d37602d501dc27e1bdbc841f174adf337909d2 )

Account State Difference:

  Address   Before After State Difference Code
0x8DB1fdfD...8435F2fc8
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 2680560236246631261141479461577455926580646999979626557512311784899546640169824937691221619954628360483898854178618979094858305403309079159291572424123613169006929406943127278266742314511673888167129742733813184002737783715429192023064402095618998095776103811662804722618834917866588198534531268686172385957094286638324445297669281294739653320911478621003513468079136441177539907269387536300756143284155909231477113635254214699758274732763242798771092752692733205990401064053348930363081832799032136663088494269980293223514571086120823309838568048978137805338903541493431002866029367692070376840734354019503927200597638659801602883768396669232152399197253677164926981795935068023397160345526476471295535102443111030749140414777239025543491218619815170754553325764005120956713557025154887053295323854693444489015487761786952032843991682543419567182649584177768803134499034005775295441545439026137911359188703278685514525111775606309227831921105164522697872321556209026613847437655140006110781543431970134555570840149238994225837655520648917557136614232137343894353071454190328255856230702911939967167084100613180970493254395997200646119252259260670127744825997551973975596214058893933484808040211154523346394700988578015538528864467466567493624079589009617077361957683855856626510092807691986881739367861327929946703253695690818813818051379090244808244514856862695521301017248992876433959943711084437781130540302635562481184528877375207441197616228910081097826347897440457995468934970468662982967188184370984589351570973917780557437127306715781020105353596706486815669474278895589711202777001474200673280807456603935237122201461419508386850089327845528104675733858374655112325644260770153063333875879516340067183310759236474523519274803377345863094041826658884953708689849027794982278074247674515232058057099657168146257524748255162521285804267848119116803748377300798457842804409336937569995263612349014886630440016390124689742715594682090743762752089184534681196742481875741607872150624830990652190674240582532396563340485371440760932953788874512231014668324313632667372895860387133894085721283811954733392535710956631900700250578786817568393665977875592596400711177048476324342091056466255779515921265505985063736728518424547807092698418744370124203089638043720011371207923522616027187885288834153412933615099643943442440787995125213956354806407496771007035922434888484098989113040345311417347459243185395223896257546472310947671326826430549303965630619138433734150412270602764023305151461690230616937896121923565269936875149979822928235872028527796004897273174827571894318990464285542258626895868006510094034276375670696999328730204466972278088004504942471272367102641118985991131906331112827926267873550014934194434262945793189906174457475816176437132318730195122161200109569297565703450080746042247441460557677385819452986587890391919133989238800255994820154008927262959456754871499665420990267593807937323969610847630272423248805433099852848924071989033765789919328795017218135052319704632070382939988304815767920317564072050260947524107886965155261594832275474969900048669337448905945673825944076730354133711587155148264022832914044267892895412446948455549669759064147662501277810338942451635661536031529366629054237773856987238378496217599069953953272698971259579536302112214340053341761393569934743184545082008041734803146933184260865606324699254725815147773274436264972388622731285409682801024402103331337989765648921904310339375636519340301236249513233935914327032924439869594795670231176071324887625378144320677187497224935676217589750864425640290472185113313008636001641831629898757155759459154880937179912553610776620703772623783294600726220720832402329971893448486944508526419435371944994395592460948634141010248038096841957087436609738639382945216668222358517722570912918082929164877885997122874186463100003169103524794843732419673145203102011363008788535682670588296315811421450015021177203054447840255045601429908162794780671497012103804173598403400914846099005509601014571769945950348483972673703998981909235978559209476760089486056860399736286079945758164982594756647521865193473341162965490262216626711949289955008638413534225120354582198286542303329952582474017217155593629627765982214886399211152131821100634386333014437874395577723335063054161965388267276671578876360021925901486938679584981128926850719670908926636468190942420924967501695061964032400567292998982111479929404581130591759187080305771282321989266350372452404751059653233966375350012367089825348879987502354573695848285278416675672015305107293477189187521973510093758261277199401911518193130708656835167302817524463277234541297687870759381079607674884137909478476510215778238136057856591426627861716200659483666313836095254253360583189652068035752362909526976554365327348300963860775644535363407867078151374919672778056304330416908292827560857069313667393113925895905463022785300804922401355507294208599080169426087773505497495432695302653299452138883878149383159722979102696004112258140002732607252951835707832840069425465117980553226445753150780160335036809750431632846654816607595182126485547799195388023781678648744560533344852396718271226740106351663848542219758260107195515982630319727486605541961705941080122678058134601957172507888270132453410007901066196322664954615000877205552792665919992774915014044648973046502699307305716799987222895008870023682782877092833374999290341719133385881671411306085177254059448305684777591607383906140085932395409864085976040166130406037573493624364637526830293868055701585448551169279597173629454490417583197920472563270700112842643469506891298414104235153448268318056612580885741922408923196636398395604066463667251176766074341157752927819783762558656559075579993628450265110754040222406304521921341790443384248649276406840725102774133948444520324087373676640598711475071906575415852067143922395234542379691130027244855017436734461973628648907764893713754525629132711130591776526422435494588849549397724508742108620243834833548283590398080241485262160919407455076617032760341350944657517819126670810756229917384351453231096778308892941110345732423204154745531586036540649002041496185922690543613917245316653576280272695302856174095977350108856035175103069879173493805555137719184939109264758280613091962262501634299657823497814179691261443801698521459805704475028496820397613409429894681900108850761557003390352689818916171638949534954308909658267748069200372802527852677243672142043433559383036519060360705238530161024515314488806997080645540987590762312373349813690118398792715919158423169947526669586720788689548120094296333459279995045004532245286019859320854858094006989829511638101920844926618846159341073212910942281874540728349758466607669449685893689050050357511406515065599099917764088189852714582478194080613030044830596839918886463567694703458883264295257617310773663995750170446108352725402762212820065478147257329428597164120656952032902107794370677762924610413299099191869009648546186315361541814011282755748037727237145548398941821082291667800165156354537383001792782710870387753915860920720667296865180367751167587614676894386157514937107970326535359916940756598265440338029376127152619558136663162664376773100422933769192333798809111643289932331146060233594336506424523931831024872764539729889031820366201709631589340927922048270502323733237535659707887667320115517697088519927487730322156831318001259535526550473366918844274269391479803293651144129747415154341588513570902557371320384377930567197086137241097561700582385083855979661648005639270198531021373649208068299401590428995271038586569819816450113540497180876998405521870075939953290683125572695224086257222332719757375540827708477563804770916951276128085223067060588647320306351826680467943881734274896384670210552045222036097079497589251032310361876984881642003495623561635871993021645188889638983301146001263623389406291079173816361660518659593119915506278802022023357797097719558828935948788697893332371721703638137767271853194043922789700704242563788021486793680620910660572101352274701984645432546891504992299463158863857952253467867338799646472944908453336410376099657863582359693529436691833410661433163832992679800926259056280047592045025648743275106909905335409665264333182204166572360677229497366112869983743550483196717483947127444187288513592743290770374411010087460119036236457407524491250589046955958397966480475827240817709615795246864112578964334658107740252241086771857778687534640720960236021370539785734749216498416231885125225811859206771902137689845879753204624715983204883221794401700378617196921081126222131027230319824277039256083059633874188353284714839391691095447728914152766953194377725218322676081016197157888396401629095555761058055918901704057231390863464892449626234131050086794716581051622561843443447413286641818664987105557960795752321141913146203916467436405148735041459140426558216278350592316674835548220237434676376052612629059393772542429035806517729203096791398501289365833895073933166976516993238960430573416207089998830701852103308138133272895465827649815609133181308565520653516852929353303451224914984728551723194359699107662131103891378768435097973240944704238707445064708699127597189898313241421701690802887672595118003258820973004976343519927361027295011651637371481032628978692016932245293914819035346924680313095145122063377276485499824892468143167766038858609260432759256324723540664850412648582971848704318777837117810732280703509267080074565944164026335759901728631645183452921315122039092801917616173133449339708337064815443025383097755069227558206708492640627791053969848252031164105264175240519835078054998308168301609944664429835441650740531282049155860408477146106280324102216023510323235352128544437383177102699443237843036671227553631812743295147276251752698131581572529938719399601067423285041034898915512821439697818140186618102065103149465168440721702883575486391104227016904264057324595322212478986264966103421849212319081083888099124103170539273933665120711726460859692495494661593993802855451872169599448763656674048033374183821752873367473826912054748392297558386750105452413144970014642940698612609847683525033987453480171779827374958751278125208473422635794948236525938179920859422877161413154573769119595321537599893517746447505091919326845540968686421006801762791075686525288876086600853359348441919455640748035899829003705143875337047743866714060102406343170331091875593230948597742773130510737432090485383026887393369870751508071089066025230658927725841278833299686232056474060520673588963274337840351476343480664918685732701525168617568414088375206626297679342364793896011953725554289296386339413173052959985984558851592796918663320271532599047504381355817728318343776493809277183146139568148208242666077398283433807063557010905607289913848088617611972015009949620273035620417876041299024084238273558379938652056923484919436646688937535406983994006415489533259330234431267690980866056178119098203455277838900513476197000926059291133817896506341305548331676466256490979890667083267890320735839094547168293885218042264329718680201227378490568345666408332204299483728499987452957578167719502712573542704590656682627268652185179688474011452772469024504610517142851106220043340016991310852274740437834107767147076701286635180947625279254289919866077673276899353760862054502426478442397474037680677130038778536585544526918654461046168134218662943518982920494709587427925366814180184501742168478478383331952499977098565477065828304464785236875259201744551546250579906420805324985755785187082373732282658068986986767444664982512309608977335747092691551407536026466235018370726512189814045899401116758242033998141765006383778564138102763200259481131495840696589908722665506549733961854421633054723573383649341308254936886371721230556224449639418581242737387341287598870121576129631947233395663458381089481726471799474459932667118653718788596491869447843829667833856684894052942634068590189378334606076749174160137437941864832955540669271069167195543638244789886393281217004492789361081264228254350706456340578736766708500695501929909459520270638122883477672537348305203530624665709764100143214511951660807612144404204461263482354175903026254684304644433901383555034046273135085011494060430653215670858859629823349242590226451531786974280833866276001233962029671929412399904636483562533959039266710184074752953124450224759543738900085231651132627987673133754537831800984916252909272290772928239715299296792371143162482533606167227342151823693593911333574878829799575323383666710967159642696965148499955919025839394569427016114565650316426692972112890520032142981200391401428601360131094543706676542615568708997986373106569819132807910247811177279936490904289291192003395919244392808204436015092347405183719917406538158471183298727382831750016577407734160070962670579269522044649033760323037399188626693433652915834461497975605745253358265059835699828819362745090760770681646078015232599826207888294339444987154507262594177724871900121467849217124692292495770205113587654063247983106116786473047385475701829673311781629799543647692858458857839260954030112756829285094310974213404001756560642026005226893312604016977774963116891803246144685064532941429107078462383831130465762717936422220397360446320257094522487566443223511295965603199777160313707844922607221649568346738335821795600825011850843367195932625464685510428720725406384262105713146399352924826860584678640218815899962571769427874804146684430613910284305636828814034569197645383142566278991526926336676194938422332074812938184907630984465826154916268803740705246060209246005812310071390808512425207414664170758954725224631278538225148727811797329479752845397051430815459564221448576268139087331962081099642368466235199491997376162964897066608951583016139924744157438814802373370912715328220761934376982359427073287262744482148213788901192934107158605333334048727458838846040853470567152273813409974650217133343057471719304535146015139615823900548494972392147464009936316054022806028135647366083142911970322950716925054375315868264188568334903824995051331718860675397686498688066149998103365724063522852924459312318045802549408107584485456226318592339615705160400200252468180142748035178998101253094609422788685025588657177180092974344009891436526697870378324589886282434521824187189691457297663088332016817892031029379007224458541526155065274432227609111281202189184656148212188769069466967616594664135499505600329631133446132960119437489895972067368284162363201385577231559423396866667747062741083391829881973009149610891606005885044997560651768666353022999989900055507856606507452605456948204299582695204614057059697141831364671563330992739997226667018805124476261465676494454373364619485007900756174785258836618946976204117550381193024697974223377774965124766357615471660690022740783762273047635368829508403384318053367476921029955089348728585874042431532040469903127658003763596258923655334026783361049186454959334357397661078691610197077909151288967959721683221028563263599349097421580056502161913967573368746731049245592243072912680142790097813332561587305041589384833749950653712406950316208903089621970123911722538623099657795194264195619503564398883245431257893539177110334571809752860732292156726357881623307123359937656250591497712015046965902072032037970767991175490744745645488064499305617480882859523358016534938528237753906920963196378551736585629505230514885501058017845409986380726575963613065932920061867222997016036796578801408878226017379506857611588807099692108132589621048713338960000621806164762522694932252003185289805907656506376299427906488671139953095410284934473351168392534230880518854370502107249977162095631868552900570293597462966795950199819916307703645879370745212800807039537973732762230585579350559624183847621185280373418703996576470424355239871223670835029517824702507908663014147968391871122173167261524013013360354152751953833588114870244674964956307405474668921519204193322946002994
(Ethermine)
1,598.0250639396191152 Eth1,598.3337413396191152 Eth0.3086774
0xf3D37602...f337909D2
(Tokamak Network: Deployer)
8.6675968 Eth
Nonce: 66
8.3589194 Eth
Nonce: 67
0.3086774

Execution Trace

Swapper.60806040( )
// File: contracts/openzeppelin-solidity/token/ERC20/IERC20.sol

pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see `ERC20Detailed`.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a `Transfer` event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through `transferFrom`. This is
     * zero by default.
     *
     * This value changes when `approve` or `transferFrom` are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * > Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an `Approval` event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a `Transfer` event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to `approve`. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// File: contracts/openzeppelin-solidity/math/SafeMath.sol

pragma solidity ^0.5.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}

// File: contracts/openzeppelin-solidity/token/ERC20/ERC20.sol

pragma solidity ^0.5.0;



/**
 * @dev Implementation of the `IERC20` interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using `_mint`.
 * For a generic mechanism see `ERC20Mintable`.
 *
 * *For a detailed writeup see our guide [How to implement supply
 * mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an `Approval` event is emitted on calls to `transferFrom`.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard `decreaseAllowance` and `increaseAllowance`
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See `IERC20.approve`.
 */
contract ERC20 is IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    /**
     * @dev See `IERC20.totalSupply`.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See `IERC20.balanceOf`.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See `IERC20.transfer`.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev See `IERC20.allowance`.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See `IERC20.approve`.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev See `IERC20.transferFrom`.
     *
     * Emits an `Approval` event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of `ERC20`;
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `value`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in `IERC20.approve`.
     *
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in `IERC20.approve`.
     *
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to `transfer`, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a `Transfer` event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a `Transfer` event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

     /**
     * @dev Destoys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a `Transfer` event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 value) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _totalSupply = _totalSupply.sub(value);
        _balances[account] = _balances[account].sub(value);
        emit Transfer(account, address(0), value);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an `Approval` event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev Destoys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See `_burn` and `_approve`.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
    }
}

// File: contracts/openzeppelin-solidity/access/Roles.sol

pragma solidity ^0.5.0;

/**
 * @title Roles
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
    struct Role {
        mapping (address => bool) bearer;
    }

    /**
     * @dev Give an account access to this role.
     */
    function add(Role storage role, address account) internal {
        require(!has(role, account), "Roles: account already has role");
        role.bearer[account] = true;
    }

    /**
     * @dev Remove an account's access to this role.
     */
    function remove(Role storage role, address account) internal {
        require(has(role, account), "Roles: account does not have role");
        role.bearer[account] = false;
    }

    /**
     * @dev Check if an account has this role.
     * @return bool
     */
    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0), "Roles: account is the zero address");
        return role.bearer[account];
    }
}

// File: contracts/openzeppelin-solidity/access/roles/MinterRole.sol

pragma solidity ^0.5.0;


contract MinterRole {
    using Roles for Roles.Role;

    event MinterAdded(address indexed account);
    event MinterRemoved(address indexed account);

    Roles.Role private _minters;

    constructor () internal {
        _addMinter(msg.sender);
    }

    modifier onlyMinter() {
        require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role");
        _;
    }

    function isMinter(address account) public view returns (bool) {
        return _minters.has(account);
    }

    function addMinter(address account) public onlyMinter {
        _addMinter(account);
    }

    function renounceMinter() public {
        _removeMinter(msg.sender);
    }

    function _addMinter(address account) internal {
        _minters.add(account);
        emit MinterAdded(account);
    }

    function _removeMinter(address account) internal {
        _minters.remove(account);
        emit MinterRemoved(account);
    }
}

// File: contracts/openzeppelin-solidity/token/ERC20/ERC20Mintable.sol

pragma solidity ^0.5.0;



/**
 * @dev Extension of `ERC20` that adds a set of accounts with the `MinterRole`,
 * which have permission to mint (create) new tokens as they see fit.
 *
 * At construction, the deployer of the contract is the only minter.
 */
contract ERC20Mintable is ERC20, MinterRole {
    /**
     * @dev See `ERC20._mint`.
     *
     * Requirements:
     *
     * - the caller must have the `MinterRole`.
     */
    function mint(address account, uint256 amount) public onlyMinter returns (bool) {
        _mint(account, amount);
        return true;
    }
}

// File: contracts/openzeppelin-solidity/ownership/Secondary.sol

pragma solidity ^0.5.0;

/**
 * @dev A Secondary contract can only be used by its primary account (the one that created it).
 */
contract Secondary {
    address private _primary;

    /**
     * @dev Emitted when the primary contract changes.
     */
    event PrimaryTransferred(
        address recipient
    );

    /**
     * @dev Sets the primary account to the one that is creating the Secondary contract.
     */
    constructor () internal {
        _primary = msg.sender;
        emit PrimaryTransferred(_primary);
    }

    /**
     * @dev Reverts if called from any account other than the primary.
     */
    modifier onlyPrimary() {
        require(msg.sender == _primary, "Secondary: caller is not the primary account");
        _;
    }

    /**
     * @return the address of the primary.
     */
    function primary() public view returns (address) {
        return _primary;
    }

    /**
     * @dev Transfers contract to a new primary.
     * @param recipient The address of new primary.
     */
    function transferPrimary(address recipient) public onlyPrimary {
        require(recipient != address(0), "Secondary: new primary is the zero address");
        _primary = recipient;
        emit PrimaryTransferred(_primary);
    }
}

// File: contracts/minime/Controlled.sol

pragma solidity ^0.5.0;

contract Controlled {
    /// @notice The address of the controller is the only address that can call
    ///  a function with this modifier
    modifier onlyController { require(msg.sender == controller, "Controlled: caller is not the controller"); _; }

    address payable public controller;

    constructor () public { controller = msg.sender;}

    /// @notice Changes the controller of the contract
    /// @param _newController The new controller of the contract
    function changeController(address payable _newController) public onlyController {
        controller = _newController;
    }
}

// File: contracts/minime/TokenController.sol

pragma solidity ^0.5.0;

/// @dev The token controller contract must implement these functions
contract TokenController {
    /// @notice Called when `_owner` sends ether to the MiniMe Token contract
    /// @param _owner The address that sent the ether to create tokens
    /// @return True if the ether is accepted, false if it throws
    function proxyPayment(address _owner) public payable returns(bool);

    /// @notice Notifies the controller about a token transfer allowing the
    ///  controller to react if desired
    /// @param _from The origin of the transfer
    /// @param _to The destination of the transfer
    /// @param _amount The amount of the transfer
    /// @return False if the controller does not authorize the transfer
    function onTransfer(address _from, address _to, uint _amount) public returns(bool);

    /// @notice Notifies the controller about an approval allowing the
    ///  controller to react if desired
    /// @param _owner The address that calls `approve()`
    /// @param _spender The spender in the `approve()` call
    /// @param _amount The amount in the `approve()` call
    /// @return False if the controller does not authorize the approval
    function onApprove(address _owner, address _spender, uint _amount) public
        returns(bool);
}

// File: contracts/minime/MiniMeToken.sol

pragma solidity ^0.5.0;

/*
    Copyright 2016, Jordi Baylina

    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/>.
 */

/// @title MiniMeToken Contract
/// @author Jordi Baylina
/// @dev This token contract's goal is to make it easy for anyone to clone this
///  token using the token distribution at a given block, this will allow DAO's
///  and DApps to upgrade their features in a decentralized manner without
///  affecting the original token
/// @dev It is ERC20 compliant, but still needs to under go further testing.



contract ApproveAndCallFallBack {
    function receiveApproval(address from, uint256 _amount, address _token, bytes memory _data) public;
}

/// @dev The actual token contract, the default controller is the msg.sender
///  that deploys the contract, so usually this token will be deployed by a
///  token controller contract, which Giveth will call a "Campaign"
contract MiniMeToken is Controlled {

    string public name;                //The Token's name: e.g. DigixDAO Tokens
    uint8 public decimals;             //Number of decimals of the smallest unit
    string public symbol;              //An identifier: e.g. REP
    string public version = 'MMT_0.2'; //An arbitrary versioning scheme


    /// @dev `Checkpoint` is the structure that attaches a block number to a
    ///  given value, the block number attached is the one that last changed the
    ///  value
    struct  Checkpoint {

        // `fromBlock` is the block number that the value was generated from
        uint128 fromBlock;

        // `value` is the amount of tokens at a specific block number
        uint128 value;
    }

    // `parentToken` is the Token address that was cloned to produce this token;
    //  it will be 0x0 for a token that was not cloned
    MiniMeToken public parentToken;

    // `parentSnapShotBlock` is the block number from the Parent Token that was
    //  used to determine the initial distribution of the Clone Token
    uint public parentSnapShotBlock;

    // `creationBlock` is the block number that the Clone Token was created
    uint public creationBlock;

    // `balances` is the map that tracks the balance of each address, in this
    //  contract when the balance changes the block number that the change
    //  occurred is also included in the map
    mapping (address => Checkpoint[]) balances;

    // `allowed` tracks any extra transfer rights as in all ERC20 tokens
    mapping (address => mapping (address => uint256)) allowed;

    // Tracks the history of the `totalSupply` of the token
    Checkpoint[] totalSupplyHistory;

    // Flag that determines if the token is transferable or not.
    bool public transfersEnabled;

    // The factory used to create new clone tokens
    MiniMeTokenFactory public tokenFactory;

////////////////
// Constructor
////////////////

    /// @notice Constructor to create a MiniMeToken
    /// @param _tokenFactory The address of the MiniMeTokenFactory contract that
    ///  will create the Clone token contracts, the token factory needs to be
    ///  deployed first
    /// @param _parentToken Address of the parent token, set to 0x0 if it is a
    ///  new token
    /// @param _parentSnapShotBlock Block of the parent token that will
    ///  determine the initial distribution of the clone token, set to 0 if it
    ///  is a new token
    /// @param _tokenName Name of the new token
    /// @param _decimalUnits Number of decimals of the new token
    /// @param _tokenSymbol Token Symbol for the new token
    /// @param _transfersEnabled If true, tokens will be able to be transferred
    constructor (
        address _tokenFactory,
        address payable _parentToken,
        uint _parentSnapShotBlock,
        string memory _tokenName,
        uint8 _decimalUnits,
        string memory  _tokenSymbol,
        bool _transfersEnabled
    ) public {
        tokenFactory = MiniMeTokenFactory(_tokenFactory);
        name = _tokenName;                                 // Set the name
        decimals = _decimalUnits;                          // Set the decimals
        symbol = _tokenSymbol;                             // Set the symbol
        parentToken = MiniMeToken(_parentToken);
        parentSnapShotBlock = _parentSnapShotBlock;
        transfersEnabled = _transfersEnabled;
        creationBlock = block.number;
    }


///////////////////
// ERC20 Methods
///////////////////

    /// @notice Send `_amount` tokens to `_to` from `msg.sender`
    /// @param _to The address of the recipient
    /// @param _amount The amount of tokens to be transferred
    /// @return Whether the transfer was successful or not
    function transfer(address _to, uint256 _amount) public returns (bool success) {
        require(transfersEnabled, "MiniMeToken: transfer is not enable");
        doTransfer(msg.sender, _to, _amount);
        return true;
    }

    /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it
    ///  is approved by `_from`
    /// @param _from The address holding the tokens being transferred
    /// @param _to The address of the recipient
    /// @param _amount The amount of tokens to be transferred
    /// @return True if the transfer was successful
    function transferFrom(address _from, address _to, uint256 _amount
    ) public returns (bool success) {

        // The controller of this contract can move tokens around at will,
        //  this is important to recognize! Confirm that you trust the
        //  controller of this contract, which in most situations should be
        //  another open source smart contract or 0x0
        if (msg.sender != controller) {
            require(transfersEnabled, "MiniMeToken: transfer is not enable");

            // The standard ERC 20 transferFrom functionality
            require(allowed[_from][msg.sender] >= _amount);
            allowed[_from][msg.sender] -= _amount;
        }
        doTransfer(_from, _to, _amount);
        return true;
    }

    /// @dev This is the actual transfer function in the token contract, it can
    ///  only be called by other functions in this contract.
    /// @param _from The address holding the tokens being transferred
    /// @param _to The address of the recipient
    /// @param _amount The amount of tokens to be transferred
    /// @return True if the transfer was successful
    function doTransfer(address _from, address _to, uint _amount
    ) internal {

           if (_amount == 0) {
               emit Transfer(_from, _to, _amount);    // Follow the spec to louch the event when transfer 0
               return;
           }

           require(parentSnapShotBlock < block.number);

           // Do not allow transfer to 0x0 or the token contract itself
           require((_to != address(0)) && (_to != address(this)));

           // If the amount being transfered is more than the balance of the
           //  account the transfer throws
           uint previousBalanceFrom = balanceOfAt(_from, block.number);

           require(previousBalanceFrom >= _amount);

           // Alerts the token controller of the transfer
           if (isContract(controller)) {
               require(TokenController(controller).onTransfer(_from, _to, _amount));
           }

           // First update the balance array with the new value for the address
           //  sending the tokens
           updateValueAtNow(balances[_from], previousBalanceFrom - _amount);

           // Then update the balance array with the new value for the address
           //  receiving the tokens
           uint previousBalanceTo = balanceOfAt(_to, block.number);
           require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
           updateValueAtNow(balances[_to], previousBalanceTo + _amount);

           // An event to make the transfer easy to find on the blockchain
           emit Transfer(_from, _to, _amount);

    }

    /// @param _owner The address that's balance is being requested
    /// @return The balance of `_owner` at the current block
    function balanceOf(address _owner) public view returns (uint256 balance) {
        return balanceOfAt(_owner, block.number);
    }

    /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on
    ///  its behalf. This is a modified version of the ERC20 approve function
    ///  to be a little bit safer
    /// @param _spender The address of the account able to transfer the tokens
    /// @param _amount The amount of tokens to be approved for transfer
    /// @return True if the approval was successful
    function approve(address _spender, uint256 _amount) public returns (bool success) {
        require(transfersEnabled, "MiniMeToken: transfer is not enable");

        // To change the approve amount you first have to reduce the addresses`
        //  allowance to zero by calling `approve(_spender,0)` if it is not
        //  already 0 to mitigate the race condition described here:
        //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
        require((_amount == 0) || (allowed[msg.sender][_spender] == 0));

        // Alerts the token controller of the approve function call
        if (isContract(controller)) {
            require(TokenController(controller).onApprove(msg.sender, _spender, _amount));
        }

        allowed[msg.sender][_spender] = _amount;
        emit Approval(msg.sender, _spender, _amount);
        return true;
    }

    /// @dev This function makes it easy to read the `allowed[]` map
    /// @param _owner The address of the account that owns the token
    /// @param _spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens of _owner that _spender is allowed
    ///  to spend
    function allowance(address _owner, address _spender
    ) public view returns (uint256 remaining) {
        return allowed[_owner][_spender];
    }

    /// @notice `msg.sender` approves `_spender` to send `_amount` tokens on
    ///  its behalf, and then a function is triggered in the contract that is
    ///  being approved, `_spender`. This allows users to use their tokens to
    ///  interact with contracts in one function call instead of two
    /// @param _spender The address of the contract able to transfer the tokens
    /// @param _amount The amount of tokens to be approved for transfer
    /// @return True if the function call was successful
    function approveAndCall(address _spender, uint256 _amount, bytes memory _extraData
    ) public returns (bool success) {
        require(approve(_spender, _amount));

        ApproveAndCallFallBack(_spender).receiveApproval(
            msg.sender,
            _amount,
            address(this),
            _extraData
        );

        return true;
    }

    /// @dev This function makes it easy to get the total number of tokens
    /// @return The total number of tokens
    function totalSupply() public view returns (uint) {
        return totalSupplyAt(block.number);
    }


////////////////
// Query balance and totalSupply in History
////////////////

    /// @dev Queries the balance of `_owner` at a specific `_blockNumber`
    /// @param _owner The address from which the balance will be retrieved
    /// @param _blockNumber The block number when the balance is queried
    /// @return The balance at `_blockNumber`
    function balanceOfAt(address _owner, uint _blockNumber) public view
        returns (uint) {

        // These next few lines are used when the balance of the token is
        //  requested before a check point was ever created for this token, it
        //  requires that the `parentToken.balanceOfAt` be queried at the
        //  genesis block for that token as this contains initial balance of
        //  this token
        if ((balances[_owner].length == 0)
            || (balances[_owner][0].fromBlock > _blockNumber)) {
            if (address(parentToken) != address(0)) {
                return parentToken.balanceOfAt(_owner, min(_blockNumber, parentSnapShotBlock));
            } else {
                // Has no parent
                return 0;
            }

        // This will return the expected balance during normal situations
        } else {
            return getValueAt(balances[_owner], _blockNumber);
        }
    }

    /// @notice Total amount of tokens at a specific `_blockNumber`.
    /// @param _blockNumber The block number when the totalSupply is queried
    /// @return The total amount of tokens at `_blockNumber`
    function totalSupplyAt(uint _blockNumber) public view returns(uint) {

        // These next few lines are used when the totalSupply of the token is
        //  requested before a check point was ever created for this token, it
        //  requires that the `parentToken.totalSupplyAt` be queried at the
        //  genesis block for this token as that contains totalSupply of this
        //  token at this block number.
        if ((totalSupplyHistory.length == 0)
            || (totalSupplyHistory[0].fromBlock > _blockNumber)) {
            if (address(parentToken) != address(0)) {
                return parentToken.totalSupplyAt(min(_blockNumber, parentSnapShotBlock));
            } else {
                return 0;
            }

        // This will return the expected totalSupply during normal situations
        } else {
            return getValueAt(totalSupplyHistory, _blockNumber);
        }
    }

////////////////
// Clone Token Method
////////////////

    /// @notice Creates a new clone token with the initial distribution being
    ///  this token at `_snapshotBlock`
    /// @param _cloneTokenName Name of the clone token
    /// @param _cloneDecimalUnits Number of decimals of the smallest unit
    /// @param _cloneTokenSymbol Symbol of the clone token
    /// @param _snapshotBlock Block when the distribution of the parent token is
    ///  copied to set the initial distribution of the new clone token;
    ///  if the block is zero than the actual block, the current block is used
    /// @param _transfersEnabled True if transfers are allowed in the clone
    /// @return The address of the new MiniMeToken Contract
    function createCloneToken(
        string memory _cloneTokenName,
        uint8 _cloneDecimalUnits,
        string memory _cloneTokenSymbol,
        uint _snapshotBlock,
        bool _transfersEnabled
        ) public returns(address) {
        if (_snapshotBlock == 0) _snapshotBlock = block.number;
        MiniMeToken cloneToken = tokenFactory.createCloneToken(
            address(this),
            _snapshotBlock,
            _cloneTokenName,
            _cloneDecimalUnits,
            _cloneTokenSymbol,
            _transfersEnabled
            );

        cloneToken.changeController(msg.sender);

        // An event to make the token easy to find on the blockchain
        emit NewCloneToken(address(cloneToken), _snapshotBlock);
        return address(cloneToken);
    }

////////////////
// Generate and destroy tokens
////////////////

    /// @notice Generates `_amount` tokens that are assigned to `_owner`
    /// @param _owner The address that will be assigned the new tokens
    /// @param _amount The quantity of tokens generated
    /// @return True if the tokens are generated correctly
    function generateTokens(address _owner, uint _amount
    ) public onlyController returns (bool) {
        uint curTotalSupply = totalSupply();
        require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow
        uint previousBalanceTo = balanceOf(_owner);
        require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow
        updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
        updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
        emit Transfer(address(0), _owner, _amount);
        return true;
    }


    /// @notice Burns `_amount` tokens from `_owner`
    /// @param _owner The address that will lose the tokens
    /// @param _amount The quantity of tokens to burn
    /// @return True if the tokens are burned correctly
    function destroyTokens(address _owner, uint _amount
    ) onlyController public returns (bool) {
        uint curTotalSupply = totalSupply();
        require(curTotalSupply >= _amount);
        uint previousBalanceFrom = balanceOf(_owner);
        require(previousBalanceFrom >= _amount);
        updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
        updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
        emit Transfer(_owner, address(0), _amount);
        return true;
    }

////////////////
// Enable tokens transfers
////////////////


    /// @notice Enables token holders to transfer their tokens freely if true
    /// @param _transfersEnabled True if transfers are allowed in the clone
    function enableTransfers(bool _transfersEnabled) public onlyController {
        transfersEnabled = _transfersEnabled;
    }

////////////////
// Internal helper functions to query and set a value in a snapshot array
////////////////

    /// @dev `getValueAt` retrieves the number of tokens at a given block number
    /// @param checkpoints The history of values being queried
    /// @param _block The block number to retrieve the value at
    /// @return The number of tokens being queried
    function getValueAt(Checkpoint[] storage checkpoints, uint _block
    ) view internal returns (uint) {
        if (checkpoints.length == 0) return 0;

        // Shortcut for the actual value
        if (_block >= checkpoints[checkpoints.length-1].fromBlock)
            return checkpoints[checkpoints.length-1].value;
        if (_block < checkpoints[0].fromBlock) return 0;

        // Binary search of the value in the array
        uint min = 0;
        uint max = checkpoints.length-1;
        while (max > min) {
            uint mid = (max + min + 1)/ 2;
            if (checkpoints[mid].fromBlock<=_block) {
                min = mid;
            } else {
                max = mid-1;
            }
        }
        return checkpoints[min].value;
    }

    /// @dev `updateValueAtNow` used to update the `balances` map and the
    ///  `totalSupplyHistory`
    /// @param checkpoints The history of data being updated
    /// @param _value The new number of tokens
    function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value
    ) internal  {
        if ((checkpoints.length == 0)
        || (checkpoints[checkpoints.length -1].fromBlock < block.number)) {
               Checkpoint storage newCheckPoint = checkpoints[ checkpoints.length++ ];
               newCheckPoint.fromBlock =  uint128(block.number);
               newCheckPoint.value = uint128(_value);
           } else {
               Checkpoint storage oldCheckPoint = checkpoints[checkpoints.length-1];
               oldCheckPoint.value = uint128(_value);
           }
    }

    /// @dev Internal function to determine if an address is a contract
    /// @param _addr The address being queried
    /// @return True if `_addr` is a contract
    function isContract(address _addr) view internal returns(bool) {
        uint size;
        if (_addr == address(0)) return false;
        assembly {
            size := extcodesize(_addr)
        }
        return size>0;
    }

    /// @dev Helper function to return a min betwen the two uints
    function min(uint a, uint b) pure internal returns (uint) {
        return a < b ? a : b;
    }

    /// @notice The fallback function: If the contract's controller has not been
    ///  set to 0, then the `proxyPayment` method is called which relays the
    ///  ether and creates tokens as described in the token controller contract
    function () external payable {
        require(isContract(controller));
        require(TokenController(controller).proxyPayment.value(msg.value)(msg.sender));
    }

//////////
// Safety Methods
//////////

    /// @notice This method can be used by the controller to extract mistakenly
    ///  sent tokens to this contract.
    /// @param _token The address of the token contract that you want to recover
    ///  set to 0 in case you want to extract ether.
    function claimTokens(address payable _token) public onlyController {
        if (_token == address(0)) {
            controller.transfer(address(this).balance);
            return;
        }

        MiniMeToken token = MiniMeToken(_token);
        uint balance = token.balanceOf(address(this));
        token.transfer(controller, balance);
        emit ClaimedTokens(_token, controller, balance);
    }

////////////////
// Events
////////////////
    event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount);
    event Transfer(address indexed _from, address indexed _to, uint256 _amount);	
    event NewCloneToken(address indexed _cloneToken, uint _snapshotBlock);
    event Approval(	
        address indexed _owner,	
        address indexed _spender,	
        uint256 _amount	
        );
}


////////////////
// MiniMeTokenFactory
////////////////

/// @dev This contract is used to generate clone contracts from a contract.
///  In solidity this is the way to create a contract from a contract of the
///  same class
contract MiniMeTokenFactory {

    /// @notice Update the DApp by creating a new token with new functionalities
    ///  the msg.sender becomes the controller of this clone token
    /// @param _parentToken Address of the token being cloned
    /// @param _snapshotBlock Block of the parent token that will
    ///  determine the initial distribution of the clone token
    /// @param _tokenName Name of the new token
    /// @param _decimalUnits Number of decimals of the new token
    /// @param _tokenSymbol Token Symbol for the new token
    /// @param _transfersEnabled If true, tokens will be able to be transferred
    /// @return The address of the new token contract
    function createCloneToken(
        address payable _parentToken,
        uint _snapshotBlock,
        string memory _tokenName,
        uint8 _decimalUnits,
        string memory _tokenSymbol,
        bool _transfersEnabled
    ) public returns (MiniMeToken) {
        MiniMeToken newToken = new MiniMeToken(
            address(this),
            _parentToken,
            _snapshotBlock,
            _tokenName,
            _decimalUnits,
            _tokenSymbol,
            _transfersEnabled
            );

        newToken.changeController(msg.sender);
        return newToken;
    }
}

// File: contracts/VestingTokenStep.sol

pragma solidity ^0.5.0;



contract VestingTokenStep is MiniMeToken {
    using SafeMath for uint256;

    bool public initiated;

    // Durations and timestamps are expressed in UNIX time, the same units as block.timestamp.
    uint256 public cliff;
    uint256 public start;
    uint256 public duration;
    uint256 public constant UNIT_IN_SECONDS = 60 * 60 * 24 * 30;

    mapping (address => uint256) public released;

    constructor (
        address tokenFactory,
        address payable parentToken,
        uint parentSnapShotBlock,
        string memory tokenName,
        uint8 decimalUnits,
        string memory tokenSymbol,
        bool transfersEnabled
    )
        public
        MiniMeToken(tokenFactory, parentToken, parentSnapShotBlock, tokenName, decimalUnits, tokenSymbol, transfersEnabled)
    {
        // solhint-disable-previous-line no-empty-blocks
    }

    modifier beforeInitiated() {
        require(!initiated, "VestingTokenStep: cannot execute after initiation");
        _;
    }

    modifier afterInitiated() {
        require(initiated, "VestingTokenStep: cannot execute before initiation");
        _;
    }

    /**
     * @notice Makes vested tokens releasable.
     * @param _start the time (as Unix time) at which point vesting starts
     * @param cliffDuration duration in unit(30 days) of the cliff in which tokens will begin to vest
     * @param _duration duration in unit(30 days) of the period in which the tokens will vest(after the cliff period)
     */
    function initiate(uint256 _start, uint256 cliffDuration, uint256 _duration) public beforeInitiated onlyController {
        initiated = true;

        enableTransfers(false);

        // solhint-disable-next-line max-line-length
        require(cliffDuration <= _duration, "VestingTokenStep: cliff is longer than duration");
        require(_duration != 0, "VestingTokenStep: duration is 0");
        // solhint-disable-next-line max-line-length
        require(_start.add(_duration.mul(UNIT_IN_SECONDS)) > block.timestamp, "VestingTokenStep: final time is before current time");

        duration = _duration;
        start = _start;
        cliff = start.add(cliffDuration.mul(UNIT_IN_SECONDS));
    }

    /**
     * @dev This is the actual transfer function in the token contract.
     * @param from The address holding the tokens being transferred
     * @param to The address of the recipient
     * @param amount The amount of tokens to be transferred
     */
    function doTransfer(address from, address to, uint amount) internal beforeInitiated {
        super.doTransfer(from, to, amount);
    }

    /**
     * @notice Destroys releasable tokens.
     * @param beneficiary the beneficiary of the tokens.
     */
    function destroyReleasableTokens(address beneficiary) public afterInitiated onlyController returns (uint256 unreleased) {
        unreleased = releasableAmount(beneficiary);

        require(unreleased != 0, "VestingTokenStep: no tokens are due");

        released[beneficiary] = released[beneficiary].add(unreleased);

        require(destroyTokens(beneficiary, unreleased), "VestingTokenStep: failed to destroy tokens");
    }

    /**
     * @dev Calculates the amount that has already vested but hasn't been released yet.
     * @param beneficiary the beneficiary of the tokens.
     */
    function releasableAmount(address beneficiary) public view returns (uint256) {
        return _vestedAmount(beneficiary).sub(released[beneficiary]);
    }

    /**
     * @dev Calculates the amount that has already vested.
     * @param beneficiary the beneficiary of the tokens.
     */
    function _vestedAmount(address beneficiary) private view returns (uint256) {
        if (!initiated) {
            return 0;
        }

        uint256 currentVestedAmount = balanceOf(beneficiary);
        uint256 totalVestedAmount = currentVestedAmount.add(released[beneficiary]);

        if (block.timestamp < cliff) {
            return 0;
        } else if (block.timestamp >= cliff.add(duration.mul(UNIT_IN_SECONDS))) {
            return totalVestedAmount;
        } else {
            uint256 currenUnit = block.timestamp.sub(cliff).div(UNIT_IN_SECONDS).add(1);
            return totalVestedAmount.mul(currenUnit).div(duration);
        }
    }
}

// File: contracts/TONVault.sol

pragma solidity ^0.5.0;




contract TONVault is Secondary {
    using SafeMath for uint256;

    ERC20Mintable public ton;

    constructor (ERC20Mintable tonToken) public {
        ton = tonToken;
    }

    function setApprovalAmount(address approval, uint256 amount) public onlyPrimary {
        ton.approve(approval, amount);
    }
    
    function withdraw(uint256 amount, address recipient) public onlyPrimary {
        ton.transfer(recipient, amount);
    }
}

// File: contracts/Burner.sol

pragma solidity ^0.5.0;

contract Burner {
    constructor () public {
    }
}

// File: contracts/Swapper.sol

pragma solidity ^0.5.0;








contract Swapper is Secondary {
    using SafeMath for uint256;

    mapping(address => uint256) public ratio;

    ERC20Mintable public _token;
    IERC20 public mton;
    TONVault public vault;
    address public constant burner = 0x0000000000000000000000000000000000000001;
    uint256 public startTimestamp;

    event Swapped(address account, uint256 unreleased, uint256 transferred);
    event Withdrew(address recipient, uint256 amount);
    event UpdateRatio(address vestingToken, uint256 tokenRatio);
    event SetVault(address vaultAddress);

    modifier onlyBeforeStart() {
        require(block.timestamp < startTimestamp || startTimestamp == 0, "Swapper: cannot execute after start");
        _;
    }

    constructor (ERC20Mintable token, address mtonAddress) public {
        _token = token;
        mton = IERC20(mtonAddress);
    }

    function updateRatio(address vestingToken, uint256 tokenRatio) external onlyPrimary onlyBeforeStart {
        ratio[vestingToken] = tokenRatio;
        emit UpdateRatio(vestingToken, tokenRatio);
    }

    function setStart(uint256 _startTimestamp) external onlyPrimary {
        require(startTimestamp == 0, "Swapper: the starttime is already set");
        startTimestamp = _startTimestamp;
    }

    function swap(address payable vestingToken) external returns (bool) {
        uint256 tokenRatio = ratio[vestingToken];
        require(tokenRatio != 0, "VestingSwapper: not valid sale token address");

        uint256 unreleased = releasableAmount(vestingToken, msg.sender);
        if (unreleased == 0) {
            return true;
        }

        if (vestingToken == address(mton)) {
            mton.transferFrom(msg.sender, address(this), unreleased);
            mton.transfer(burner, unreleased);
        } else {
            unreleased = VestingTokenStep(vestingToken).destroyReleasableTokens(msg.sender);
        }
        uint256 ton_amount = unreleased.mul(tokenRatio);
        _token.transferFrom(address(vault), address(this), ton_amount);
        _token.transfer(msg.sender, ton_amount);
        
        emit Swapped(msg.sender, unreleased, ton_amount);
        return true;
    }

    // TokenController

    /// @notice Called when `_owner` sends ether to the MiniMe Token contract
    /// @param _owner The address that sent the ether to create tokens
    /// @return True if the ether is accepted, false if it throws
    function proxyPayment(address _owner) public payable returns(bool) {
        return true;
    }

    /// @notice Notifies the controller about a token transfer allowing the
    ///  controller to react if desired
    /// @param _from The origin of the transfer
    /// @param _to The destination of the transfer
    /// @param _amount The amount of the transfer
    /// @return False if the controller does not authorize the transfer
    function onTransfer(address _from, address _to, uint _amount) public returns(bool) {
        return true;
    }

    /// @notice Notifies the controller about an approval allowing the
    ///  controller to react if desired
    /// @param _owner The address that calls `approve()`
    /// @param _spender The spender in the `approve()` call
    /// @param _amount The amount in the `approve()` call
    /// @return False if the controller does not authorize the approval
    function onApprove(address _owner, address _spender, uint _amount) public returns(bool) {
        return true;
    }

    function releasableAmount(address payable vestingToken, address beneficiary) public view returns (uint256) {
        if (vestingToken == address(mton)) {
            return mton.balanceOf(beneficiary);
        } else {
            return VestingTokenStep(vestingToken).releasableAmount(beneficiary);
        }
    }

    function changeController(VestingTokenStep vestingToken, address payable newController) external onlyPrimary {
        vestingToken.changeController(newController);
    }

    function setVault(TONVault vaultAddress) external onlyPrimary {
        vault = vaultAddress;
        emit SetVault(address(vaultAddress));
    }
}