nevillegrech / gigahorse-toolchain

A binary lifter and analysis framework for Ethereum smart contracts
Other
296 stars 61 forks source link

Pathological contract example #12

Closed beaugunderson closed 2 years ago

beaugunderson commented 3 years ago

This contract never finishes decompilation: 0xaeb960ed44c8a4ce848c50ef451f472a503456b2

In my attempts with gigahorse the process is eventually killed after consuming all memory.

It's one of the Sorare contracts, currently containing $3m worth of ETH. I believe it's the contract used for purchasing cards on their platform.

By comparison, Panoramix gives a partial decompilation but fails on function 223da1ba.

sifislag commented 3 years ago

Hi, thanks for reporting this issue. I took a look and manually decompiled the contract. I tried two things:

  1. Using the latest master I was able to decompile it at 1m42s using souffle's interpreted mode, or 58s using compiled mode, while the process took around 2G of RAM. The difference between what you are reporting and what I am is probably due to me using the latest version of gigahorse as a recent change greatly help with our ability to provide output for such pathological contracts. The decompilation was not perfect however. Looking into the cause of that.
  2. I manually changed the maximum context depth of the transactional context of our decompiler by editing this line: https://github.com/nevillegrech/gigahorse-toolchain/blob/d6a1010cd99c537d19fbfcd72efd8b04ebc0c318/logic/context-sensitivity/transactional-context.dl#L17 The new value I set was 8 and this produced a much better decompilation (also faster, at just 4s). I'm attaching the decompilation output:
// Decompiled at www.contract-library.com
// 2021.05.11 07:02 UTC

// Data structures and variables inferred from the use of storage instructions
mapping (uint256 => [uint256]) _getRoleAdmin; // STORAGE[0x1]
mapping (uint256 => [uint256]) _getAccountBalance; // STORAGE[0x3]
mapping (uint256 => [uint256]) _startExit; // STORAGE[0x4]
mapping (uint256 => [uint256]) map_5; // STORAGE[0x5]
mapping (uint256 => [uint256]) map_6; // STORAGE[0x6]
mapping (uint256 => [uint256]) map_7; // STORAGE[0x7]
uint256 stor_8; // STORAGE[0x8]
uint256 _getTaxRate; // STORAGE[0x9]
uint256 stor_a; // STORAGE[0xa]
mapping (uint256 => [uint256]) _cancelDeal; // STORAGE[0xb]
address _owner; // STORAGE[0x0] bytes 0 to 19
address _nonFungibleContract; // STORAGE[0x2] bytes 0 to 19
uint8 stor_0_20_20; // STORAGE[0x0] bytes 20 to 20

// Events
Closed();
OwnershipTransferred(address, address);
RoleGranted(bytes32, address, address);
RoleRevoked(bytes32, address, address);

function fallback() public payable { 
    revert();
}

function getBalance() public nonPayable { 
    require(_owner == msg.sender, 'Ownable: caller is not the owner');
    return stor_a;
}

function 0x1d0b013a(address varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    0x5eaa(varg0);
    return 0xff & map_5[varg0];
}

function 0x2338(uint256 varg0, uint256 varg1) private { 
    v0 = address(varg0);
    v1 = 1 + keccak256(varg1, 1);
    return STORAGE[keccak256(v0, v1)] != 0;
}

function 0x223da1ba(uint256 varg0, address varg1, address varg2, address varg3, uint256 varg4, uint256 varg5) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 192);
    require(msg.data[4] <= 0xffffffffffffffff);
    require(4 + (msg.data.length - 4) - (4 + msg.data[4]) >= 224);
    v0 = MEM[64];
    require(!((v0 + 224 > 0xffffffffffffffff) | (v0 + 224 < v0)));
    MEM[64] = v0 + 224;
    require(msg.data[4 + msg.data[4] + 0] == msg.data[4 + msg.data[4] + 0]);
    0x5eaa(msg.data[4 + msg.data[4] + 32]);
    0x5eaa(msg.data[4 + msg.data[4] + 64]);
    require(msg.data[4 + msg.data[4] + 96] == msg.data[4 + msg.data[4] + 96]);
    require(msg.data[4 + msg.data[4] + 128] == msg.data[4 + msg.data[4] + 128]);
    require(msg.data[4 + msg.data[4] + 160] <= 0xffffffffffffffff);
    require(4 + msg.data[4] + msg.data[4 + msg.data[4] + 160] + 31 < 4 + (msg.data.length - 4));
    require(msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 160]] <= 0xffffffffffffffff);
    v1 = new uint256[](msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 160]]);
    require(!((v1 + ((msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 160]] << 5) + 32) > 0xffffffffffffffff) | (v1 + ((msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 160]] << 5) + 32) < v1)));
    v2 = v3 = 4 + msg.data[4] + msg.data[4 + msg.data[4] + 160] + 32;
    v4 = v5 = v1.data;
    require(v3 + (msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 160]] << 5) <= 4 + (msg.data.length - 4));
    v6 = v7 = 0;
    while (v6 < msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 160]]) {
        require(msg.data[v2] == msg.data[v2]);
        MEM[v4] = msg.data[v2];
        v4 = v4 + 32;
        v2 = v2 + 32;
        v6 = v6 + 1;
    }
    require(msg.data[4 + msg.data[4] + 192] <= 0xffffffffffffffff);
    require(4 + msg.data[4] + msg.data[4 + msg.data[4] + 192] + 31 < 4 + (msg.data.length - 4));
    require(msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 192]] <= 0xffffffffffffffff);
    v8 = new uint256[](msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 192]]);
    require(!((v8 + ((msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 192]] << 5) + 32) > 0xffffffffffffffff) | (v8 + ((msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 192]] << 5) + 32) < v8)));
    v9 = v10 = 4 + msg.data[4] + msg.data[4 + msg.data[4] + 192] + 32;
    v11 = v12 = v8.data;
    require(v10 + (msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 192]] << 5) <= 4 + (msg.data.length - 4));
    v13 = v14 = 0;
    while (v13 < msg.data[4 + msg.data[4] + msg.data[4 + msg.data[4] + 192]]) {
        require(msg.data[v9] == msg.data[v9]);
        MEM[v11] = msg.data[v9];
        v11 = v11 + 32;
        v9 = v9 + 32;
        v13 = v13 + 1;
    }
    0x5eaa(varg1);
    0x5eaa(varg2);
    0x5eaa(varg3);
    require(varg4 == varg4);
    require(msg.data[164] <= 0xffffffffffffffff);
    require(4 + (msg.data.length - 4) - (4 + msg.data[164]) >= 192);
    require(!((MEM[64] + 192 > 0xffffffffffffffff) | (MEM[64] + 192 < MEM[64])));
    MEM[64] = MEM[64] + 192;
    require(msg.data[4 + msg.data[164] + 0] <= 0xffffffffffffffff);
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 0] + 31 < 4 + (msg.data.length - 4));
    require(msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 0]] <= 0xffffffffffffffff);
    v15 = new bytes[](msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 0]]);
    require(!((v15 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 0]] + 31 & ~0x1f) + 32) > 0xffffffffffffffff) | (v15 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 0]] + 31 & ~0x1f) + 32) < v15)));
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 0] + 32 + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 0]] <= 4 + (msg.data.length - 4));
    CALLDATACOPY(v15.data, 4 + msg.data[164] + msg.data[4 + msg.data[164] + 0] + 32, msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 0]]);
    MEM[v15.data + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 0]]] = 0;
    require(msg.data[4 + msg.data[164] + 32] <= 0xffffffffffffffff);
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 32] + 31 < 4 + (msg.data.length - 4));
    require(msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 32]] <= 0xffffffffffffffff);
    v16 = new bytes[](msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 32]]);
    require(!((v16 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 32]] + 31 & ~0x1f) + 32) > 0xffffffffffffffff) | (v16 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 32]] + 31 & ~0x1f) + 32) < v16)));
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 32] + 32 + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 32]] <= 4 + (msg.data.length - 4));
    CALLDATACOPY(v16.data, 4 + msg.data[164] + msg.data[4 + msg.data[164] + 32] + 32, msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 32]]);
    MEM[v16.data + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 32]]] = 0;
    require(msg.data[4 + msg.data[164] + 64] <= 0xffffffffffffffff);
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 64] + 31 < 4 + (msg.data.length - 4));
    require(msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 64]] <= 0xffffffffffffffff);
    v17 = new bytes[](msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 64]]);
    require(!((v17 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 64]] + 31 & ~0x1f) + 32) > 0xffffffffffffffff) | (v17 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 64]] + 31 & ~0x1f) + 32) < v17)));
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 64] + 32 + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 64]] <= 4 + (msg.data.length - 4));
    CALLDATACOPY(v17.data, 4 + msg.data[164] + msg.data[4 + msg.data[164] + 64] + 32, msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 64]]);
    MEM[v17.data + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 64]]] = 0;
    require(msg.data[4 + msg.data[164] + 96] <= 0xffffffffffffffff);
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 96] + 31 < 4 + (msg.data.length - 4));
    require(msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 96]] <= 0xffffffffffffffff);
    v18 = new bytes[](msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 96]]);
    require(!((v18 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 96]] + 31 & ~0x1f) + 32) > 0xffffffffffffffff) | (v18 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 96]] + 31 & ~0x1f) + 32) < v18)));
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 96] + 32 + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 96]] <= 4 + (msg.data.length - 4));
    CALLDATACOPY(v18.data, 4 + msg.data[164] + msg.data[4 + msg.data[164] + 96] + 32, msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 96]]);
    MEM[v18.data + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 96]]] = 0;
    require(msg.data[4 + msg.data[164] + 128] <= 0xffffffffffffffff);
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 128] + 31 < 4 + (msg.data.length - 4));
    require(msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 128]] <= 0xffffffffffffffff);
    v19 = new bytes[](msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 128]]);
    require(!((v19 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 128]] + 31 & ~0x1f) + 32) > 0xffffffffffffffff) | (v19 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 128]] + 31 & ~0x1f) + 32) < v19)));
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 128] + 32 + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 128]] <= 4 + (msg.data.length - 4));
    CALLDATACOPY(v19.data, 4 + msg.data[164] + msg.data[4 + msg.data[164] + 128] + 32, msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 128]]);
    MEM[v19.data + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 128]]] = 0;
    require(msg.data[4 + msg.data[164] + 160] <= 0xffffffffffffffff);
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 160] + 31 < 4 + (msg.data.length - 4));
    require(msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 160]] <= 0xffffffffffffffff);
    v20 = new bytes[](msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 160]]);
    require(!((v20 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 160]] + 31 & ~0x1f) + 32) > 0xffffffffffffffff) | (v20 + ((msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 160]] + 31 & ~0x1f) + 32) < v20)));
    require(4 + msg.data[164] + msg.data[4 + msg.data[164] + 160] + 32 + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 160]] <= 4 + (msg.data.length - 4));
    CALLDATACOPY(v20.data, 4 + msg.data[164] + msg.data[4 + msg.data[164] + 160] + 32, msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 160]]);
    MEM[v20.data + msg.data[4 + msg.data[164] + msg.data[4 + msg.data[164] + 160]]] = 0;
    v21 = 0x2338(msg.sender, keccak256('SIGNER_ROLE'));
    require(v21, 'Sender is not a signer');
    v22 = v23 = !(0xff & _cancelDeal[msg.data[4 + msg.data[4] + 0]]);
    if (v23) {
        v22 = !(0xff & _cancelDeal[msg.data[4 + msg.data[4] + 0]]);
    }
    require(v22, 'Deal settled or cancelled');
    v24 = v25 = address(msg.data[4 + msg.data[4] + 64]) == 0;
    if (address(msg.data[4 + msg.data[4] + 64]) != 0) {
        v24 = address(msg.data[4 + msg.data[4] + 64]) == varg1;
    }
    require(v24, 'Invalid receiver');
    require(varg4 >= msg.data[4 + msg.data[4] + 128], 'Amount received too low');
    v26 = v27 = MEM[64];
    MEM[64] = 64 + v27;
    v28 = v29 = 2;
    while (1) {
        MEM[64] += 192;
        MEM[MEM[64]] = 0;
        MEM[32 + MEM[64]] = 0;
        MEM[64 + MEM[64]] = 0;
        MEM[96 + MEM[64]] = 96;
        MEM[128 + MEM[64]] = 0;
        MEM[160 + MEM[64]] = 0;
        MEM[v26] = MEM[64];
        v26 += 32;
        v28 = v28 - 1;
        if (v28) {
            break;
        }
        if (!v28) {
            MEM[64] += 64;
            MEM[64] += 192;
            MEM[MEM[64]] = varg3;
            MEM[32 + MEM[64]] = varg1;
            MEM[64 + MEM[64]] = msg.data[4 + msg.data[4] + 96];
            MEM[96 + MEM[64]] = v15;
            MEM[128 + MEM[64]] = 0;
            MEM[160 + MEM[64]] = 0;
            MEM[MEM[64]] = MEM[64];
            MEM[64] += 192;
            MEM[MEM[64]] = varg2;
            MEM[32 + MEM[64]] = address(msg.data[4 + msg.data[4] + 32]);
            MEM[64 + MEM[64]] = varg4;
            MEM[96 + MEM[64]] = v18;
            MEM[128 + MEM[64]] = 3;
            MEM[160 + MEM[64]] = varg4;
            MEM[32 + MEM[64]] = MEM[64];
            MEM[MEM[64]] = 0;
            MEM[32 + MEM[64]] = 0;
            MEM[64 + MEM[64]] = 96;
            MEM[96 + MEM[64]] = 96;
            MEM[128 + MEM[64]] = 0;
            MEM[32 + MEM[64]] = varg1;
            require(MEM[v1] <= 0xffffffffffffffff);
            v30 = new uint256[](MEM[v1]);
            if (MEM[v1]) {
                CALLDATACOPY(v30.data, msg.data.length, MEM[v1] << 5);
            }
            MEM[96 + MEM[64]] = v16;
            MEM[128 + MEM[64]] = 1;
            MEM[MEM[64]] = 0;
            MEM[32 + MEM[64]] = 0;
            MEM[64 + MEM[64]] = 96;
            MEM[96 + MEM[64]] = 96;
            MEM[128 + MEM[64]] = 0;
            MEM[32 + MEM[64]] = varg1;
            require(MEM[v1] <= 0xffffffffffffffff);
            v31 = new uint256[](MEM[v1]);
            if (MEM[v1]) {
                CALLDATACOPY(v31.data, msg.data.length, MEM[v1] << 5);
            }
            MEM[96 + MEM[64]] = v17;
            MEM[128 + MEM[64]] = 2;
            MEM[MEM[64]] = 0;
            MEM[32 + MEM[64]] = 0;
            MEM[64 + MEM[64]] = 96;
            MEM[96 + MEM[64]] = 96;
            MEM[128 + MEM[64]] = 0;
            MEM[32 + MEM[64]] = address(msg.data[4 + msg.data[4] + 32]);
            require(MEM[v8] <= 0xffffffffffffffff);
            v32 = new uint256[](MEM[v8]);
            if (MEM[v8]) {
                CALLDATACOPY(v32.data, msg.data.length, MEM[v8] << 5);
            }
            MEM[96 + MEM[64]] = v19;
            MEM[128 + MEM[64]] = 4;
            MEM[MEM[64]] = 0;
            MEM[32 + MEM[64]] = 0;
            MEM[64 + MEM[64]] = 96;
            MEM[96 + MEM[64]] = 96;
            MEM[128 + MEM[64]] = 0;
            MEM[32 + MEM[64]] = address(msg.data[4 + msg.data[4] + 32]);
            require(MEM[v8] <= 0xffffffffffffffff);
            v33 = new uint256[](MEM[v8]);
            if (MEM[v8]) {
                CALLDATACOPY(v33.data, msg.data.length, MEM[v8] << 5);
            }
            MEM[96 + MEM[64]] = v20;
            MEM[128 + MEM[64]] = 5;
            v34 = v35 = 0;
            v36 = v37 = 0;
            v38 = v39 = 0;
            while (v38 < MEM[v1]) {
                assert(v38 < MEM[v1]);
                require(_nonFungibleContract.code.size);
                v40 = _nonFungibleContract.ownerOf(MEM[32 + (v38 << 5) + v1]).gas(msg.gas);
                require(v40); // checks call status, propagates error data on error
                MEM[64] = MEM[64] + (RETURNDATASIZE() + 31 & ~0x1f);
                require(MEM[64] + RETURNDATASIZE() - MEM[64] >= 32);
                0x5eaa(MEM[MEM[64] + 0]);
                if (address(MEM[MEM[64] + 0]) != address(msg.data[4 + msg.data[4] + 32])) {
                    if (address(MEM[MEM[64] + 0]) == address(_startExit[address(address(msg.data[4 + msg.data[4] + 32]))])) {
                        v36 += 1;
                        assert(v36 < MEM[v31]);
                        MEM[32 + (v36 << 5) + v31] = MEM[32 + (v38 << 5) + v1];
                    }
                } else {
                    v34 += 1;
                    assert(v34 < MEM[v30]);
                    MEM[32 + (v34 << 5) + v30] = MEM[32 + (v38 << 5) + v1];
                }
                v38 += 1;
            }
            require(v34 + v36 == MEM[v1], "Sender doesn't own all tokens");
            v41 = v42 = 0;
            v43 = v44 = 0;
            v45 = v46 = 0;
            while (v45 < MEM[v8]) {
                assert(v45 < MEM[v8]);
                require(_nonFungibleContract.code.size);
                v47 = _nonFungibleContract.ownerOf(MEM[32 + (v45 << 5) + v8]).gas(msg.gas);
                require(v47); // checks call status, propagates error data on error
                MEM[64] = MEM[64] + (RETURNDATASIZE() + 31 & ~0x1f);
                require(MEM[64] + RETURNDATASIZE() - MEM[64] >= 32);
                0x5eaa(MEM[MEM[64] + 0]);
                if (address(MEM[MEM[64] + 0]) != varg1) {
                    if (address(MEM[MEM[64] + 0]) == address(_startExit[address(varg1)])) {
                        v43 += 1;
                        assert(v43 < MEM[v33]);
                        MEM[32 + (v43 << 5) + v33] = MEM[32 + (v45 << 5) + v8];
                    }
                } else {
                    v41 += 1;
                    assert(v41 < MEM[v32]);
                    MEM[32 + (v41 << 5) + v32] = MEM[32 + (v45 << 5) + v8];
                }
                v45 += 1;
            }
            require(v41 + v43 == MEM[v8], "Receiver doesn't own all tokens");
            MEM[64] += 128;
            MEM[MEM[64]] = MEM[64];
            MEM[32 + MEM[64]] = MEM[64];
            MEM[64 + MEM[64]] = MEM[64];
            MEM[96 + MEM[64]] = MEM[64];
            MEM[32 + MEM[64] + 0] = msg.data[4 + msg.data[4] + 0];
            MEM[32 + MEM[64] + 32] = address(msg.data[4 + msg.data[4] + 32]);
            MEM[32 + MEM[64] + 64] = address(msg.data[4 + msg.data[4] + 64]);
            MEM[32 + MEM[64] + 96] = 256;
            MEM[32 + MEM[64] + 256] = MEM[v8];
            v48 = v49 = 32 + MEM[64] + 256 + 32;
            v50 = v51 = v8 + 32;
            v52 = v53 = 0;
            while (v52 < MEM[v8]) {
                MEM[v48] = MEM[v50];
                v48 = v48 + 32;
                v50 = v50 + 32;
                v52 = v52 + 1;
            }
            MEM[32 + MEM[64] + 128] = v48 - (32 + MEM[64]);
            MEM[v48] = MEM[v1];
            v54 = v55 = v48 + 32;
            v56 = v57 = v1 + 32;
            v58 = v59 = 0;
            while (v58 < MEM[v1]) {
                MEM[v54] = MEM[v56];
                v54 = v54 + 32;
                v56 = v56 + 32;
                v58 = v58 + 1;
            }
            MEM[32 + MEM[64] + 160] = msg.data[4 + msg.data[4] + 96];
            MEM[32 + MEM[64] + 192] = msg.data[4 + msg.data[4] + 128];
            MEM[32 + MEM[64] + 224] = address(this);
            MEM[64] = v54;
            v60 = v61 = 0;
            while (v60 < 2) {
                MEM[64] += 192;
                MEM[MEM[64]] = 0;
                MEM[32 + MEM[64]] = 0;
                MEM[64 + MEM[64]] = 0;
                MEM[96 + MEM[64]] = 96;
                MEM[128 + MEM[64]] = 0;
                MEM[160 + MEM[64]] = 0;
                if (v60 < 2) {
                    break;
                }
                assert(v60 < 2);
                v62 = MEM[(v60 << 5) + MEM[64]];
                require(_getAccountBalance[address(MEM[0 + v62])] >= MEM[64 + v62], 'Someone cannot afford this deal');
                if (MEM[64 + v62] > 0) {
                    if (MEM[160 + v62] != 0) {
                        assert(MEM[128 + v62] < 6);
                        MEM[32 + MEM[64] + 0] = MEM[128 + v62];
                        MEM[32 + MEM[64] + 32] = MEM[160 + v62];
                        MEM[32 + MEM[64] + 64] = 96;
                        MEM[32 + MEM[64] + 96] = v54 - MEM[64] - 32;
                        v63 = v64 = 0;
                        while (v63 < v54 - MEM[64] - 32) {
                            MEM[32 + MEM[64] + 96 + 32 + v63] = MEM[MEM[64] + 32 + v63];
                            v63 = v63 + 32;
                        }
                        if (v63 > v54 - MEM[64] - 32) {
                            MEM[32 + MEM[64] + 96 + 32 + (v54 - MEM[64] - 32)] = 0;
                        }
                        v65 = MEM[64];
                        MEM[v65] = 32 + MEM[64] + 96 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - v65 - 32;
                        MEM[64] = 32 + MEM[64] + 96 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f);
                    } else {
                        assert(MEM[128 + v62] < 6);
                        MEM[32 + MEM[64] + 0] = MEM[128 + v62];
                        MEM[32 + MEM[64] + 32] = 64;
                        MEM[32 + MEM[64] + 64] = v54 - MEM[64] - 32;
                        v66 = v67 = 0;
                        while (v66 < v54 - MEM[64] - 32) {
                            MEM[32 + MEM[64] + 64 + 32 + v66] = MEM[MEM[64] + 32 + v66];
                            v66 = v66 + 32;
                        }
                        if (v66 > v54 - MEM[64] - 32) {
                            MEM[32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32)] = 0;
                        }
                        v65 = v68 = MEM[64];
                        MEM[v68] = 32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - v68 - 32;
                        MEM[64] = 32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f);
                    }
                    MEM[MEM[64]] = 0x9a5f14b200000000000000000000000000000000000000000000000000000000;
                    MEM[4 + MEM[64] + 0] = 96;
                    MEM[4 + MEM[64] + 96] = MEM[v65];
                    v69 = v70 = 0;
                    while (v69 < MEM[v65]) {
                        MEM[4 + MEM[64] + 96 + 32 + v69] = MEM[v65 + 32 + v69];
                        v69 = v69 + 32;
                    }
                    if (v69 > MEM[v65]) {
                        MEM[4 + MEM[64] + 96 + 32 + MEM[v65]] = 0;
                    }
                    MEM[4 + MEM[64] + 32] = 4 + MEM[64] + 96 + 32 + (MEM[v65] + 31 & ~0x1f) - (4 + MEM[64]);
                    MEM[4 + MEM[64] + 96 + 32 + (MEM[v65] + 31 & ~0x1f)] = MEM[MEM[96 + v62]];
                    v71 = v72 = 0;
                    while (v71 < MEM[MEM[96 + v62]]) {
                        MEM[4 + MEM[64] + 96 + 32 + (MEM[v65] + 31 & ~0x1f) + 32 + v71] = MEM[MEM[96 + v62] + 32 + v71];
                        v71 = v71 + 32;
                    }
                    if (v71 > MEM[MEM[96 + v62]]) {
                        MEM[4 + MEM[64] + 96 + 32 + (MEM[v65] + 31 & ~0x1f) + 32 + MEM[MEM[96 + v62]]] = 0;
                    }
                    MEM[4 + MEM[64] + 64] = address(MEM[0 + v62]);
                    require(0xdb404188f3428f80fcac37a2ee7a3391f5d28c48.code.size);
                    v73 = 0xdb404188f3428f80fcac37a2ee7a3391f5d28c48.delegatecall(MEM[(MEM[64]) len (4 + MEM[64] + 96 + 32 + (MEM[v65] + 31 & ~0x1f) + 32 + (MEM[MEM[96 + v62]] + 31 & ~0x1f) - MEM[64])], MEM[(MEM[64]) len 0]).gas(msg.gas);
                    require(v73); // checks call status, propagates error data on error
                    stor_a = stor_a + MEM[64 + v62] * _getTaxRate / 10000;
                    v74 = _SafeAdd(MEM[64 + v62] - MEM[64 + v62] * _getTaxRate / 10000, _getAccountBalance[address(MEM[32 + v62])]);
                    _getAccountBalance[address(MEM[32 + v62])] = v74;
                    v75 = _SafeSub(MEM[64 + v62], _getAccountBalance[address(MEM[0 + v62])]);
                    _getAccountBalance[address(MEM[0 + v62])] = v75;
                    0x3bbe(MEM[0 + v62]);
                    0x3bbe(MEM[32 + v62]);
                }
                v60 += 1;
            }
            v76 = v77 = 0;
            while (v76 < 4) {
                MEM[64] += 160;
                MEM[MEM[64]] = 0;
                MEM[32 + MEM[64]] = 0;
                MEM[64 + MEM[64]] = 96;
                MEM[96 + MEM[64]] = 96;
                MEM[128 + MEM[64]] = 0;
                assert(v76 < 4);
                v78 = MEM[(v76 << 5) + MEM[64]];
                v79 = v80 = MEM[MEM[64 + v78]] > 0;
                if (v80) {
                    assert(0 < MEM[MEM[64 + v78]]);
                    v79 = MEM[32 + MEM[64 + v78]] != 0;
                }
                if (v79) {
                    assert(MEM[128 + v78] < 6);
                    MEM[32 + MEM[64] + 0] = MEM[128 + v78];
                    MEM[32 + MEM[64] + 32] = 64;
                    MEM[32 + MEM[64] + 64] = v54 - MEM[64] - 32;
                    v81 = v82 = 0;
                    while (v81 < v54 - MEM[64] - 32) {
                        MEM[32 + MEM[64] + 64 + 32 + v81] = MEM[MEM[64] + 32 + v81];
                        v81 = v81 + 32;
                    }
                    if (v81 > v54 - MEM[64] - 32) {
                        MEM[32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32)] = 0;
                    }
                    MEM[64] = 32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f);
                    MEM[MEM[64]] = 0x9a5f14b200000000000000000000000000000000000000000000000000000000;
                    MEM[4 + MEM[64] + 0] = 96;
                    MEM[4 + MEM[64] + 96] = 32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - MEM[64] - 32;
                    v83 = v84 = 0;
                    while (v83 < 32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - MEM[64] - 32) {
                        MEM[4 + MEM[64] + 96 + 32 + v83] = MEM[MEM[64] + 32 + v83];
                        v83 = v83 + 32;
                    }
                    if (v83 > 32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - MEM[64] - 32) {
                        MEM[4 + MEM[64] + 96 + 32 + (32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - MEM[64] - 32)] = 0;
                    }
                    MEM[4 + MEM[64] + 32] = 4 + MEM[64] + 96 + 32 + (32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - MEM[64] - 32 + 31 & ~0x1f) - (4 + MEM[64]);
                    MEM[4 + MEM[64] + 96 + 32 + (32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - MEM[64] - 32 + 31 & ~0x1f)] = MEM[MEM[96 + v78]];
                    v85 = v86 = 0;
                    while (v85 < MEM[MEM[96 + v78]]) {
                        MEM[4 + MEM[64] + 96 + 32 + (32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - MEM[64] - 32 + 31 & ~0x1f) + 32 + v85] = MEM[MEM[96 + v78] + 32 + v85];
                        v85 = v85 + 32;
                    }
                    if (v85 > MEM[MEM[96 + v78]]) {
                        MEM[4 + MEM[64] + 96 + 32 + (32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - MEM[64] - 32 + 31 & ~0x1f) + 32 + MEM[MEM[96 + v78]]] = 0;
                    }
                    MEM[4 + MEM[64] + 64] = address(MEM[0 + v78]);
                    require(0xdb404188f3428f80fcac37a2ee7a3391f5d28c48.code.size);
                    v87 = 0xdb404188f3428f80fcac37a2ee7a3391f5d28c48.delegatecall(MEM[(MEM[64]) len (4 + MEM[64] + 96 + 32 + (32 + MEM[64] + 64 + 32 + (v54 - MEM[64] - 32 + 31 & ~0x1f) - MEM[64] - 32 + 31 & ~0x1f) + 32 + (MEM[MEM[96 + v78]] + 31 & ~0x1f) - MEM[64])], MEM[(MEM[64]) len 0]).gas(msg.gas);
                    require(v87); // checks call status, propagates error data on error
                    v88 = v89 = MEM[32 + v78];
                    if (0xff & map_5[address(MEM[32 + v78])]) {
                        v88 = v90 = address(_startExit[address(address(MEM[32 + v78]))]);
                    }
                    MEM[MEM[64]] = 0x4012576500000000000000000000000000000000000000000000000000000000;
                    v91 = 0x5dd1(_nonFungibleContract);
                    MEM[4 + MEM[64] + 0] = v91;
                    MEM[4 + MEM[64] + 32] = address(MEM[0 + v78]);
                    MEM[4 + MEM[64] + 64] = address(v88);
                    MEM[4 + MEM[64] + 96] = 128;
                    MEM[4 + MEM[64] + 128] = MEM[MEM[64 + v78]];
                    v92 = v93 = 4 + MEM[64] + 128 + 32;
                    v94 = v95 = MEM[64 + v78] + 32;
                    v96 = v97 = 0;
                    while (v96 < MEM[MEM[64 + v78]]) {
                        MEM[v92] = MEM[v94];
                        v92 = v92 + 32;
                        v94 = v94 + 32;
                        v96 = v96 + 1;
                    }
                    require(0xe2fd97cdd6182c1223ff8bc6344abaf7132b51d5.code.size);
                    v98 = 0xe2fd97cdd6182c1223ff8bc6344abaf7132b51d5.delegatecall(MEM[(MEM[64]) len (v92 - MEM[64])], MEM[(MEM[64]) len 0]).gas(msg.gas);
                    require(v98); // checks call status, propagates error data on error
                }
                v76 += 1;
            }
            _cancelDeal[msg.data[4 + msg.data[4] + 0]] = 0x1 | ~0xff & _cancelDeal[msg.data[4 + msg.data[4] + 0]];
            v99 = new array[](msg.data[4 + msg.data[4] + 0]);
            MEM[v99.data] = address(msg.data[4 + msg.data[4] + 32]);
            v100 = v101 = v99 + 224 + 32;
            v102 = v103 = v1 + 32;
            v104 = v105 = 0;
            while (v104 < MEM[v1]) {
                MEM[v100] = MEM[v102];
                v100 = v100 + 32;
                v102 = v102 + 32;
                v104 = v104 + 1;
            }
            MEM[v100] = MEM[v8];
            v106 = v107 = v100 + 32;
            v108 = v109 = v8 + 32;
            v110 = v111 = 0;
            while (v110 < MEM[v8]) {
                MEM[v106] = MEM[v108];
                v106 = v106 + 32;
                v108 = v108 + 32;
                v110 = v110 + 1;
            }
            emit 0x43eb744b69e2ba057b09224246fa56336142aad9761bcd000ffd900a59431795(msg.data[4 + msg.data[4] + 0], v99 + 0, varg1, varg4, varg2, varg3, v112, v112, address(msg.data[4 + msg.data[4] + 64]), msg.data[4 + msg.data[4] + 96], msg.data[4 + msg.data[4] + 128], 224, v100 - v99, MEM[v1]);
            exit;
        }
    }
}

function getRoleAdmin(bytes32 varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    require(varg0 == varg0);
    return _getRoleAdmin[varg0][2];
}

function grantRole(bytes32 varg0, address varg1) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 64);
    require(varg0 == varg0);
    0x5eaa(varg1);
    v0 = 0x2338(msg.sender, _getRoleAdmin[varg0][2]);
    require(v0, 'AccessControl: sender must be an admin to grant');
    if (STORAGE[keccak256(varg1, 1 + keccak256(varg0, 1))] != 0) {
        v1 = v2 = 0;
    } else {
        STORAGE[0 + keccak256(varg0, 1)] = STORAGE[0 + keccak256(varg0, 1)] + 1;
        STORAGE[keccak256(0 + keccak256(varg0, 1)) + (STORAGE[0 + keccak256(varg0, 1)] + 1 - 1)] = varg1;
        STORAGE[keccak256(varg1, 1 + keccak256(varg0, 1))] = STORAGE[0 + keccak256(varg0, 1)];
        v1 = v3 = 1;
    }
    if (v1) {
        emit RoleGranted(varg0, varg1, msg.sender);
    }
}

function cancelDeal(uint256 varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    require(varg0 == varg0);
    _cancelDeal[varg0] = 0x1 | ~0xff & _cancelDeal[varg0];
    emit 0xbb65c9fbe1575a117b12b3ff94d93e0cf5579b98c1f91992d89747d53d2bf1e1(varg0, msg.sender);
}

function renounceRole(bytes32 varg0, address varg1) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 64);
    require(varg0 == varg0);
    0x5eaa(varg1);
    require(varg1 == msg.sender, 'AccessControl: can only renounce roles for self');
    0x3831(varg1, varg0);
}

function close() public nonPayable { 
    require(_owner == msg.sender, 'Ownable: caller is not the owner');
    require(!stor_0_20_20, 'The contract is already closed');
    stor_0_20_20 = 1;
    emit Closed();
}

function withdrawBalance() public nonPayable { 
    require(_owner == msg.sender, 'Ownable: caller is not the owner');
    v0 = msg.sender.call().value(stor_a).gas(!stor_a * 2300);
    require(v0); // checks call status, propagates error data on error
    stor_a = 0;
}

function 0x6db61a3a(address varg0, uint256 varg1) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 64);
    0x5eaa(varg0);
    require(varg1 == varg1);
    require(address(_startExit[address(varg0)]) == msg.sender, 'Invalid sender');
    0x38c5(varg1, varg0);
}

function renounceOwnership() public nonPayable { 
    require(_owner == msg.sender, 'Ownable: caller is not the owner');
    emit OwnershipTransferred(_owner, 0);
    _owner = 0;
}

function 0x3831(uint256 varg0, uint256 varg1) private { 
    v0 = 0 + keccak256(varg1, 1);
    v1 = address(varg0);
    if (STORAGE[keccak256(v1, 1 + v0)] == 0) {
        v2 = v3 = 0;
    } else {
        assert(STORAGE[0 + v0] - 1 < STORAGE[0 + v0]);
        assert(STORAGE[keccak256(v1, 1 + v0)] - 1 < STORAGE[0 + v0]);
        STORAGE[keccak256(0 + v0) + (STORAGE[keccak256(v1, 1 + v0)] - 1)] = STORAGE[keccak256(0 + v0) + (STORAGE[0 + v0] - 1)];
        STORAGE[keccak256(STORAGE[keccak256(0 + v0) + (STORAGE[0 + v0] - 1)], 1 + v0)] = STORAGE[keccak256(v1, 1 + v0)] - 1 + 1;
        assert(STORAGE[0 + v0]);
        STORAGE[keccak256(0 + v0) + (STORAGE[0 + v0] - 1)] = 0;
        STORAGE[0 + v0] = STORAGE[0 + v0] - 1;
        STORAGE[keccak256(v1, 1 + v0)] = 0;
        v2 = v4 = 1;
    }
    if (v2) {
        emit RoleRevoked(varg1, address(varg0), msg.sender);
    }
    return ;
}

function 0x72233c5e(address varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    0x5eaa(varg0);
    return address(_startExit[address(varg0)]);
}

function 0x38c5(uint256 varg0, uint256 varg1) private { 
    v0 = address(varg1);
    map_5[v0] = varg0 | ~0xff & map_5[v0];
    if (varg0) {
        v1 = 0x5dd1(_nonFungibleContract);
        v2 = address(varg1);
        require(0xe2fd97cdd6182c1223ff8bc6344abaf7132b51d5.code.size);
        v3 = 0xe2fd97cdd6182c1223ff8bc6344abaf7132b51d5.delegatecall(0xdc800b0d, v1, v2, msg.sender).gas(msg.gas);
        require(v3); // checks call status, propagates error data on error
    }
    return ;
}

function _SafeAdd(uint256 varg0, uint256 varg1) private { 
    v0 = varg1 + varg0;
    require(v0 >= varg1, 'SafeMath: addition overflow');
    return v0;
}

function 0x3bbe(uint256 varg0) private { 
    v0 = address(varg0);
    v1 = address(varg0);
    emit 0xd03c77ba06fdea91615ddd289bcef4a278bcbf729ba06c5d12b6fd9d5a0998d2(address(varg0), address(_startExit[v0]), _getAccountBalance[v1]);
    return ;
}

function startExit(address varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    0x5eaa(varg0);
    require(address(_startExit[address(varg0)]) == msg.sender, 'Invalid exit request');
    map_7[varg0] = block.number;
    emit 0x2b0e9b8cbd31d536823d3f755d033dcb387b88ba7516509c68c1c589d094d2a4(varg0, msg.sender, _getAccountBalance[varg0]);
}

function _SafeSub(uint256 varg0, uint256 varg1) private { 
    if (varg0 <= varg1) {
        return varg1 - varg0;
    } else {
        v0 = new array[](v1.length);
        v2 = v3 = 0;
        while (v2 < v1.length) {
            MEM[v0.data + v2] = MEM[v1.data + v2];
            v2 = v2 + 32;
        }
        if (v2 > v1.length) {
            MEM[v0.data + v1.length] = 0;
        }
        revert(v0, v4, 'SafeMath: subtraction overflow');
    }
}

function 0x7901451c(address varg0, uint256 varg1, uint256 varg2) public payable { 
    require(4 + (msg.data.length - 4) - 4 >= 96);
    0x5eaa(varg0);
    require(varg1 <= 0xffffffffffffffff);
    require(4 + varg1 + 31 < 4 + (msg.data.length - 4));
    require(varg1.length <= 0xffffffffffffffff);
    require(4 + varg1 + 32 + varg1.length <= 4 + (msg.data.length - 4));
    require(varg2 == varg2);
    require(!stor_0_20_20, 'The Cash Desk is closed');
    require(map_7[varg0] == 0, 'This account has started an exit');
    v0 = v1 = address(_startExit[address(varg0)]) == 0;
    if (v1) {
        v0 = v2 = varg1.length > 0;
    }
    if (v0) {
        v3 = new bytes[](varg1.length);
        CALLDATACOPY(v3.data, 4 + varg1 + 32, varg1.length);
        MEM[v3.data + varg1.length] = 0;
        assert(0 < 2);
        v4 = new array[](96);
        v5 = v6 = 0;
        while (v5 < 96) {
            MEM[v4.data + v5] = MEM[MEM[64] + 32 + v5];
            v5 = v5 + 32;
        }
        if (v5 > 96) {
            v7 = new array[](v3.length);
        }
        v8 = new array[](v3.length);
        v9 = v10 = 0;
        while (v9 < v3.length) {
            MEM[v7.data + v9] = MEM[v3.data + v9];
            v9 = v9 + 32;
        }
        if (v9 > v3.length) {
            MEM[v7.data + v3.length] = 0;
        }
        require(0xdb404188f3428f80fcac37a2ee7a3391f5d28c48.code.size);
        v11 = 0xdb404188f3428f80fcac37a2ee7a3391f5d28c48.delegatecall(0x9a5f14b2, v4, v8, varg0, v12, 0, msg.sender, address(this)).gas(msg.gas);
        require(v11); // checks call status, propagates error data on error
        _startExit[varg0] = msg.sender | ~0xffffffffffffffffffffffffffffffffffffffff & _startExit[varg0];
        0x38c5(varg2, varg0);
        emit 0x26a2537c93fc595a8d3ee575e493c0532b9ccfa8b697cdb891247d17f42f57bd(varg0, msg.sender, varg2);
    }
    v13 = _SafeAdd(msg.value, _getAccountBalance[varg0]);
    _getAccountBalance[varg0] = v13;
    emit 0x37ee5428d74f1c45c57e5cb3ad1d96821cc0253dee9a72dbb0d292fdacdd5b9c(varg0, msg.sender, address(_getAccountBalance[address(varg0)]), msg.value);
    0x3bbe(varg0);
}

function 0x83a49477(address varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    0x5eaa(varg0);
    require(map_7[varg0] > 0, 'Exit has not been started');
    require(block.number - map_7[varg0] > stor_8, 'Should wait');
    require(address(_startExit[address(varg0)]) == msg.sender, 'Invalid exit request');
    _getAccountBalance[varg0] = 0;
    v0 = 0x5448(MEM[64]);
    v1, v2 = msg.sender.call(MEM[(MEM[64]) len (v0 - MEM[64])], MEM[(MEM[64]) len 0]).value(_getAccountBalance[varg0]).gas(msg.gas);
    if (RETURNDATASIZE() != 0) {
        v3 = new bytes[](RETURNDATASIZE());
        v2 = v3.data;
        RETURNDATACOPY(v2, 0, RETURNDATASIZE());
    }
    require(v1, 'Exit failed');
    emit 0x118d92c77160df0500b9c5f32463b43de2ef5202c79a624349ee7b5021a46e4(varg0, msg.sender, _getAccountBalance[varg0]);
    0x3bbe(varg0);
}

function owner() public nonPayable { 
    return _owner;
}

function getRoleMember(bytes32 varg0, uint256 varg1) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 64);
    require(varg0 == varg0);
    require(varg1 == varg1);
    require(STORAGE[0 + keccak256(varg0, 1)] > varg1, 'EnumerableSet: index out of bounds');
    assert(varg1 < STORAGE[0 + keccak256(varg0, 1)]);
    return address(STORAGE[keccak256(0 + keccak256(varg0, 1)) + varg1]);
}

function hasRole(bytes32 varg0, address varg1) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 64);
    require(varg0 == varg0);
    0x5eaa(varg1);
    v0 = 0x2338(varg1, varg0);
    return v0;
}

function getAccountBalance(address varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    0x5eaa(varg0);
    return _getAccountBalance[varg0];
}

function 0x96726af6(address varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    0x5eaa(varg0);
    return map_6[varg0];
}

function 0x5448(uint256 varg0) private { 
    return varg0 + 0;
}

function SIGNER_ROLE() public nonPayable { 
    return keccak256('SIGNER_ROLE');
}

function DEFAULT_ADMIN_ROLE() public nonPayable { 
    return 0;
}

function 0xab273e18(address varg0, uint256 varg1, uint256 varg2, uint256 varg3) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 128);
    0x5eaa(varg0);
    require(varg1 == varg1);
    require(varg2 == varg2);
    require(varg3 <= 0xffffffffffffffff);
    require(4 + varg3 + 31 < 4 + (msg.data.length - 4));
    require(varg3.length <= 0xffffffffffffffff);
    require(4 + varg3 + 32 + varg3.length <= 4 + (msg.data.length - 4));
    require(varg2 > map_6[varg0], 'Nonce is invalid');
    require(_getAccountBalance[varg0] >= varg1, 'Balance is too low');
    v0 = v1 = msg.sender == address(_startExit[address(varg0)]);
    if (msg.sender != address(_startExit[address(varg0)])) {
        v0 = v2 = msg.sender == varg0;
    }
    require(v0, 'Invalid withdrawal sender');
    assert(1 < 2);
    v3 = new array[](varg1);
    MEM[v3.data] = varg2;
    v4 = new array[](160);
    v5 = v6 = 0;
    while (v5 < 160) {
        MEM[v4.data + v5] = MEM[MEM[64] + 32 + v5];
        v5 = v5 + 32;
    }
    if (v5 > 160) {
    }
    MEM[v7.data + varg3.length] = 0;
    require(0xdb404188f3428f80fcac37a2ee7a3391f5d28c48.code.size);
    v8, v9 = 0xdb404188f3428f80fcac37a2ee7a3391f5d28c48.delegatecall(0x1ed13d1b, v4, v4.data + 160, v3, 1, varg0, v10, v10, address(this)).gas(msg.gas);
    require(v8); // checks call status, propagates error data on error
    MEM[64] = MEM[64] + (RETURNDATASIZE() + 31 & ~0x1f);
    require(MEM[64] + RETURNDATASIZE() - MEM[64] >= 32);
    0x5eaa(v9);
    require(STORAGE[keccak256(address(v9), 1 + keccak256(keccak256('SIGNER_ROLE'), 1))] != 0, 'Invalid signature');
    map_6[varg0] = varg2;
    v11 = _SafeSub(varg1, map_6[varg0]);
    _getAccountBalance[varg0] = v11;
    v12 = 0x5448(MEM[64]);
    v13, v14 = address(_startExit[address(varg0)]).call(MEM[(MEM[64]) len (v12 - MEM[64])], MEM[(MEM[64]) len 0]).value(varg1).gas(msg.gas);
    if (RETURNDATASIZE() != 0) {
        v15 = new bytes[](RETURNDATASIZE());
        v14 = v15.data;
        RETURNDATACOPY(v14, 0, RETURNDATASIZE());
    }
    require(v13, 'Withdrawal failed');
    emit 0xe0a0f9c70b05a8d5e22ce7e37f2b337002b939ac28592303b0d299432d1a3faa(varg0, address(_startExit[address(varg0)]), varg2, varg1);
    0x3bbe(varg0);
}

function setTaxRate(uint256 varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    require(varg0 == varg0);
    require(_owner == msg.sender, 'Ownable: caller is not the owner');
    require(varg0 <= 10000, 'Tax should be less or equal to 10000 basis points');
    _getTaxRate = varg0;
}

function 0x5dd1(uint256 varg0) private { 
    return address(varg0);
}

function 0x5eaa(uint256 varg0) private { 
    require(varg0 == address(varg0));
    return ;
}

function getRoleMemberCount(bytes32 varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    require(varg0 == varg0);
    return STORAGE[0 + keccak256(varg0, 1)];
}

function getTaxRate() public nonPayable { 
    return _getTaxRate;
}

function 0xcfe82fe4(address varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    0x5eaa(varg0);
    v0 = v1 = address(_startExit[address(varg0)]) != 0;
    if (v1) {
        v0 = v2 = msg.sender == varg0;
        if (msg.sender != varg0) {
            v0 = v3 = msg.sender == address(_startExit[address(varg0)]);
        }
    }
    require(v0, 'Invalid unmap request');
    if (msg.sender == varg0) {
        v4 = 0x5dd1(_nonFungibleContract);
        require(0xe2fd97cdd6182c1223ff8bc6344abaf7132b51d5.code.size);
        v5 = 0xe2fd97cdd6182c1223ff8bc6344abaf7132b51d5.delegatecall(0xdc800b0d, v4, varg0, _owner).gas(msg.gas);
        require(v5); // checks call status, propagates error data on error
        v6 = _SafeAdd(_getAccountBalance[varg0], _getAccountBalance[_owner]);
        _getAccountBalance[_owner] = v6;
        _getAccountBalance[varg0] = 0;
        0x3bbe(_owner);
        0x3bbe(varg0);
    }
    0x38c5(0, varg0);
    _startExit[varg0] = ~0xffffffffffffffffffffffffffffffffffffffff & _startExit[varg0];
    emit 0x42d3988cf67ba8b0ff9e6c521341a542b4c980917d0e69a10e02be46b0de3389(varg0, address(_startExit[address(varg0)]));
}

function revokeRole(bytes32 varg0, address varg1) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 64);
    require(varg0 == varg0);
    0x5eaa(varg1);
    v0 = 0x2338(msg.sender, _getRoleAdmin[varg0][2]);
    require(v0, 'AccessControl: sender must be an admin to revoke');
    0x3831(varg1, varg0);
}

function nonFungibleContract() public nonPayable { 
    v0 = 0x5dd1(_nonFungibleContract);
    return v0;
}

function transferOwnership(address varg0) public nonPayable { 
    require(4 + (msg.data.length - 4) - 4 >= 32);
    0x5eaa(varg0);
    require(_owner == msg.sender, 'Ownable: caller is not the owner');
    require(varg0 != 0, 'Ownable: new owner is the zero address');
    emit OwnershipTransferred(_owner, varg0);
    _owner = varg0;
}

// Note: The function selector is not present in the original solidity code.
// However, we display it for the sake of completeness.

function __function_selector__(uint256 function_selector) public payable { 
    MEM[64] = 128;
    if (msg.data.length >= 4) {
        v0 = function_selector >> 224;
        if (0x8da5cb5b > v0) {
            if (0x43d726d6 > v0) {
                if (0x248a9ca3 > v0) {
                    if (0x12065fe0 == v0) {
                        getBalance();
                    } else if (0x1d0b013a == v0) {
                        0x1d0b013a();
                    } else if (0x223da1ba == v0) {
                        0x223da1ba();
                    }
                } else if (0x248a9ca3 == v0) {
                    getRoleAdmin(bytes32);
                } else if (0x2f2ff15d == v0) {
                    grantRole(bytes32,address);
                } else if (0x31ea1a39 == v0) {
                    cancelDeal(uint256);
                } else if (0x36568abe == v0) {
                    renounceRole(bytes32,address);
                }
            } else if (0x72233c5e > v0) {
                if (0x43d726d6 == v0) {
                    close();
                } else if (0x5fd8c710 == v0) {
                    withdrawBalance();
                } else if (0x6db61a3a == v0) {
                    0x6db61a3a();
                } else if (0x715018a6 == v0) {
                    renounceOwnership();
                }
            } else if (0x72233c5e == v0) {
                0x72233c5e();
            } else if (0x72cc174c == v0) {
                startExit(address);
            } else if (0x7901451c == v0) {
                0x7901451c();
            } else if (0x83a49477 == v0) {
                0x83a49477();
            }
        } else if (0xab273e18 > v0) {
            if (0x93423e9c > v0) {
                if (0x8da5cb5b == v0) {
                    owner();
                } else if (0x9010d07c == v0) {
                    getRoleMember(bytes32,uint256);
                } else if (0x91d14854 == v0) {
                    hasRole(bytes32,address);
                }
            } else if (0x93423e9c == v0) {
                getAccountBalance(address);
            } else if (0x96726af6 == v0) {
                0x96726af6();
            } else if (0xa1ebf35d == v0) {
                SIGNER_ROLE();
            } else if (0xa217fddf == v0) {
                DEFAULT_ADMIN_ROLE();
            }
        } else if (0xcfe82fe4 > v0) {
            if (0xab273e18 == v0) {
                0xab273e18();
            } else if (0xc6d69a30 == v0) {
                setTaxRate(uint256);
            } else if (0xca15c873 == v0) {
                getRoleMemberCount(bytes32);
            } else if (0xcb66667f == v0) {
                getTaxRate();
            }
        } else if (0xcfe82fe4 == v0) {
            0xcfe82fe4();
        } else if (0xd547741f == v0) {
            revokeRole(bytes32,address);
        } else if (0xdd1b7a0f == v0) {
            nonFungibleContract();
        } else if (0xf2fde38b == v0) {
            transferOwnership(address);
        }
    }
    fallback();
}
sifislag commented 3 years ago

Just added (in https://github.com/nevillegrech/gigahorse-toolchain/commit/acb92683a231f82008f5fed3de5810796dba6a20 ) an optional argument --context_depth to change the maximum context depth without changing the datalog source. Let me know if the above where helpful.

metrocoding commented 2 years ago

Just added (in acb9268 ) an optional argument --context_depth to change the maximum context depth without changing the datalog source. Let me know if the above where helpful.

can you please help me decompile mine? I send a new issue #28

metrocoding commented 2 years ago

Just added (in acb9268 ) an optional argument --context_depth to change the maximum context depth without changing the datalog source. Let me know if the above where helpful.

after debugging I finally succeeded to decompile it but it didn't give me high-level codes as you have in the above message

sifislag commented 2 years ago

On demand decompilation has been added to contract-library: https://library.dedaub.com/decompile Closing this issue.