{ parameter
    (or (or (or (pair %approve address nat)
                (pair %getAllowance (pair address address) (contract nat)))
            (or (pair %getBalance address (contract nat))
                (pair %getTotalSupply unit (contract nat))))
        (pair %transfer address (pair address nat))) ;
  storage
    (pair (big_map %accounts address (pair (map %allowances address nat) (nat %balance)))
          (nat %s)) ;
  code { LAMBDA
           (pair address (big_map address (pair (map address nat) nat)))
           (pair (map address nat) nat)
           { DUP ;
             CDR ;
             SWAP ;
             CAR ;
             GET ;
             IF_NONE { PUSH string "Owner does not have a balance" ; FAILWITH } {} } ;
         SWAP ;
         DUP ;
         DUG 2 ;
         CDR ;
         PUSH mutez 0 ;
         AMOUNT ;
         COMPARE ;
         NEQ ;
         IF { PUSH string "This contract do not accept XTZ" ; FAILWITH } {} ;
         DIG 2 ;
         CAR ;
         IF_LEFT
           { IF_LEFT
               { IF_LEFT
                   { DIG 2 ;
                     DROP ;
                     PAIR ;
                     DUP ;
                     CAR ;
                     CAR ;
                     SWAP ;
                     DUP ;
                     DUG 2 ;
                     CAR ;
                     CDR ;
                     DIG 2 ;
                     CDR ;
                     DUP ;
                     CAR ;
                     SENDER ;
                     GET ;
                     IF_NONE { PUSH nat 0 ; EMPTY_MAP address nat ; PAIR } {} ;
                     DUP ;
                     CAR ;
                     DIG 4 ;
                     DUP ;
                     DUG 5 ;
                     GET ;
                     IF_NONE
                       { PUSH unit Unit }
                       { PUSH nat 0 ;
                         SWAP ;
                         COMPARE ;
                         NEQ ;
                         IF { PUSH nat 0 ;
                              DIG 3 ;
                              DUP ;
                              DUG 4 ;
                              COMPARE ;
                              NEQ ;
                              IF { PUSH string "UnsafeAllowanceChange" ; FAILWITH } { PUSH unit Unit } }
                            { PUSH unit Unit } } ;
                     DROP ;
                     SWAP ;
                     DUP ;
                     DUG 2 ;
                     CDR ;
                     DIG 2 ;
                     CAR ;
                     DIG 2 ;
                     DUP ;
                     DUG 3 ;
                     CDR ;
                     DIG 3 ;
                     CAR ;
                     DIG 4 ;
                     DIG 5 ;
                     SWAP ;
                     SOME ;
                     SWAP ;
                     UPDATE ;
                     PAIR ;
                     SOME ;
                     SENDER ;
                     UPDATE ;
                     PAIR ;
                     NIL operation ;
                     PAIR }
                   { SWAP ;
                     DUP ;
                     DIG 2 ;
                     DUP ;
                     DUG 3 ;
                     CDR ;
                     PAIR ;
                     DIG 2 ;
                     DUP ;
                     DUG 3 ;
                     CAR ;
                     CDR ;
                     DIG 3 ;
                     CAR ;
                     CAR ;
                     PAIR ;
                     PAIR ;
                     DUP ;
                     CDR ;
                     CDR ;
                     CAR ;
                     SWAP ;
                     DUP ;
                     DUG 2 ;
                     CAR ;
                     CAR ;
                     PAIR ;
                     DIG 3 ;
                     SWAP ;
                     EXEC ;
                     CAR ;
                     SWAP ;
                     DUP ;
                     DUG 2 ;
                     CAR ;
                     CDR ;
                     GET ;
                     IF_NONE
                       { PUSH string "Spender does not have an allowance for this owner" ; FAILWITH }
                       {} ;
                     NIL operation ;
                     DIG 2 ;
                     CDR ;
                     CAR ;
                     PUSH mutez 0 ;
                     DIG 3 ;
                     TRANSFER_TOKENS ;
                     CONS ;
                     PAIR } }
               { IF_LEFT
                   { SWAP ;
                     DUP ;
                     DIG 2 ;
                     PAIR ;
                     DUP ;
                     CDR ;
                     CAR ;
                     SWAP ;
                     DUP ;
                     DUG 2 ;
                     CAR ;
                     CAR ;
                     PAIR ;
                     DIG 3 ;
                     SWAP ;
                     EXEC ;
                     NIL operation ;
                     DIG 2 ;
                     CAR ;
                     CDR ;
                     PUSH mutez 0 ;
                     DIG 3 ;
                     CDR ;
                     TRANSFER_TOKENS ;
                     CONS ;
                     PAIR }
                   { DIG 2 ;
                     DROP ;
                     SWAP ;
                     DUP ;
                     DIG 2 ;
                     CDR ;
                     PAIR ;
                     NIL operation ;
                     SWAP ;
                     DUP ;
                     DUG 2 ;
                     CAR ;
                     PUSH mutez 0 ;
                     DIG 3 ;
                     CDR ;
                     CDR ;
                     TRANSFER_TOKENS ;
                     CONS ;
                     PAIR } } }
           { DUP ;
             DUG 2 ;
             CDR ;
             CDR ;
             PAIR ;
             SWAP ;
             DUP ;
             DUG 2 ;
             CDR ;
             CAR ;
             DIG 2 ;
             CAR ;
             PAIR ;
             PAIR ;
             DUP ;
             CAR ;
             CAR ;
             SWAP ;
             DUP ;
             DUG 2 ;
             CAR ;
             CDR ;
             DIG 2 ;
             DUP ;
             DUG 3 ;
             CDR ;
             CAR ;
             DIG 3 ;
             CDR ;
             CDR ;
             DIG 2 ;
             DUP ;
             DUG 3 ;
             DIG 4 ;
             DUP ;
             DUG 5 ;
             COMPARE ;
             EQ ;
             IF { SWAP ; DROP ; SWAP ; DROP ; SWAP ; DROP ; SWAP ; DROP }
                { DUP ;
                  DIG 2 ;
                  DUP ;
                  DUG 3 ;
                  DIG 5 ;
                  DUP ;
                  DUG 6 ;
                  PAIR ;
                  PAIR ;
                  DUP ;
                  CAR ;
                  CAR ;
                  DUP ;
                  SENDER ;
                  COMPARE ;
                  NEQ ;
                  IF { SWAP ;
                       DUP ;
                       DUG 2 ;
                       CDR ;
                       CAR ;
                       SWAP ;
                       GET ;
                       IF_NONE
                         { DROP ;
                           PUSH string "is_allowed: the owner does not own any tokens." ;
                           FAILWITH }
                         { CAR ;
                           SENDER ;
                           GET ;
                           IF_NONE
                             { DROP ; PUSH bool False }
                             { SWAP ; CAR ; CDR ; SWAP ; COMPARE ; GE } } }
                     { DROP 2 ; PUSH bool True } ;
                  IF {} { PUSH string "NotEnoughAllowance" ; FAILWITH } ;
                  DUP ;
                  CAR ;
                  DIG 4 ;
                  DUP ;
                  DUG 5 ;
                  PAIR ;
                  DIG 5 ;
                  SWAP ;
                  EXEC ;
                  DUP ;
                  CDR ;
                  DIG 3 ;
                  DUP ;
                  DUG 4 ;
                  COMPARE ;
                  GT ;
                  IF { PUSH string "NotEnoughBalance" ; FAILWITH } {} ;
                  SENDER ;
                  DIG 5 ;
                  DUP ;
                  DUG 6 ;
                  COMPARE ;
                  NEQ ;
                  IF { DUP ;
                       CAR ;
                       SENDER ;
                       GET ;
                       IF_NONE
                         { PUSH string "Sender does not have an allowance for this owner" ; FAILWITH }
                         {} }
                     { DUP ; CDR } ;
                  DUP ;
                  DIG 4 ;
                  DUP ;
                  DUG 5 ;
                  COMPARE ;
                  GT ;
                  IF { PUSH string "NotEnoughAllowance" ; FAILWITH } {} ;
                  DIG 3 ;
                  DUP ;
                  DUG 4 ;
                  DIG 2 ;
                  DUP ;
                  DUG 3 ;
                  CDR ;
                  SUB ;
                  PUSH int 0 ;
                  SWAP ;
                  DUP ;
                  DUG 2 ;
                  COMPARE ;
                  GE ;
                  IF { ABS ; DIG 2 ; CAR ; PAIR }
                     { DROP ; PUSH string "balance - value is negative." ; FAILWITH } ;
                  SENDER ;
                  DIG 6 ;
                  DUP ;
                  DUG 7 ;
                  COMPARE ;
                  NEQ ;
                  IF { DIG 3 ;
                       DUP ;
                       DUG 4 ;
                       DIG 2 ;
                       SUB ;
                       PUSH int 0 ;
                       SWAP ;
                       DUP ;
                       DUG 2 ;
                       COMPARE ;
                       GE ;
                       IF { SWAP ;
                            DUP ;
                            DUG 2 ;
                            CDR ;
                            DIG 2 ;
                            CAR ;
                            DIG 2 ;
                            ABS ;
                            SOME ;
                            SENDER ;
                            UPDATE ;
                            PAIR }
                          { DROP ; PUSH string "allowance - value is negative." ; FAILWITH } }
                     { SWAP ; DROP } ;
                  SWAP ;
                  DUP ;
                  DUG 2 ;
                  CDR ;
                  DIG 2 ;
                  CAR ;
                  DIG 2 ;
                  DIG 5 ;
                  SWAP ;
                  SOME ;
                  SWAP ;
                  UPDATE ;
                  PAIR ;
                  DUP ;
                  CAR ;
                  DIG 3 ;
                  DUP ;
                  DUG 4 ;
                  GET ;
                  IF_NONE { PUSH nat 0 ; EMPTY_MAP address nat ; PAIR } {} ;
                  DIG 2 ;
                  SWAP ;
                  DUP ;
                  DUG 2 ;
                  CDR ;
                  ADD ;
                  SWAP ;
                  CAR ;
                  PAIR ;
                  SWAP ;
                  DUP ;
                  DUG 2 ;
                  CDR ;
                  DIG 2 ;
                  CAR ;
                  DIG 2 ;
                  DIG 3 ;
                  SWAP ;
                  SOME ;
                  SWAP ;
                  UPDATE ;
                  PAIR } ;
             NIL operation ;
             PAIR } } }