contract CouponPresale{
    using SafeMath for uint256;
    
    uint256 public totalSale;
    
    address public ssdTokenAddr;
    
    address public ssdDaoAddr;
    
    address public _owner;
    
    address constant usdcAddr=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
    
    mapping(address=>uint256)  public couponSale;
    
    mapping(address=>uint256)  public usdcBuy;
    
    constructor() public{
        _owner=msg.sender;
        
        //old contract data
        couponSale[0x5d4F95ceB7A6d57e742f7018aDa8Ac7705f7a9EA].add(206774676*10/8);
        couponSale[0xfd8a63085804DCB95417fe33f9E49253522c68DD].add(2007615528*10/8);
        couponSale[0x7Aa9d09A6d283F5b5ec724D7dd8fa70673553183].add(821041200*10/8);
        couponSale[0x67443683D43bdE8274acC78b3e8CE6EC6F72A1A6].add(731311560*10/8);
        couponSale[0xcFe4D656F5855D82f61786E7577ae37A192C633e].add(200000000*10/8);
        couponSale[0x75c8E2dd57927eB0373E8e201ebF582406aDcf45].add(2000000000*10/8);
    }
    
    function setRealAddrs(address dao,address ssd) public{
        require(msg.sender==_owner,'not owner');
        ssdDaoAddr=dao;
        ssdTokenAddr=ssd;
    }
    
    function buyCoupons(uint256 amount) public {
        require(block.timestamp>1608998399,'wait for start');
        require(block.timestamp<1609171199,'end');
        require(amount>=200000000,'revert');
        require(usdcBuy[msg.sender].add(amount)<=2000000000,'buy limit');
        bool ret = IERC20(usdcAddr).transferFrom(msg.sender,address(this),amount);
        require(ret,'revert');
        usdcBuy[msg.sender]=usdcBuy[msg.sender].add(amount);
        amount=amount.mul(10).div(8);
        totalSale=totalSale.add(amount);
        require(totalSale<=250000000000,'hard cap');
        couponSale[msg.sender]=couponSale[msg.sender].add(amount);
    }
    
    function withdrawUSDC() public{
        IERC20(usdcAddr).transfer(_owner,IERC20(usdcAddr).balanceOf(address(this)));
    }
    
    
    //when almost user withdrawSSD
    function withdrawLeft(uint256 amount) public{
        require(msg.sender==_owner);
        require(totalSale>200000000,'team limit');
        IERC20(ssdTokenAddr).transfer(_owner,amount);
    }
    
    function withdrawSSD(uint256 amount) public{
        require(couponSale[msg.sender]>=amount,'no coupon!');
        //calc to ssd token amount
        uint256 needSSD=amount*1e12;
        require(IERC20(ssdTokenAddr).balanceOf(address(this))>=needSSD,'not enough ssd,please wait epoch');
        couponSale[msg.sender]=couponSale[msg.sender].sub(amount);
        totalSale=totalSale.sub(amount);
        IERC20(ssdTokenAddr).transfer(msg.sender,needSSD);
    }
    
    //only trigger by team
    function advance() external {
        IAdvance(ssdDaoAddr).advance();
    }
}
function withdrawLeft(uint256 amount) public{
    require(msg.sender==_owner);
    require(totalSale>200000000,'team limit');
    IERC20(ssdTokenAddr).transfer(_owner,amount);
}

//when almost user withdrawSSD