Shkëlqimi dhe varfëria e swaps-ëve atomic

Cilat janë disavantazhet e swap-eve atomike dhe si mund t'i ndihmojnë kanalet, çfarë ndodhi rëndësishëm në hard fork-un Constantinople dhe si të veprojmë kur nuk kemi si të paguajmë gazin.

Motivacioni kryesor i çdo specialisti të sigurisë është dëshira për të shmangur përgjegjësinë.

Fati ishte më i mirëkuptueshëm, unë u largova nga ICO pa pritur transaksionin e parë të pakthyeshëm, por së shpejti e gjeta veten duke zhvilluar një exchange kripto.

Unë nuk jam aspak Mëllçi Kibalçisht, dhe një shikim i fortë është i mjaftueshëm që unë të dorëzoj të gjitha çelësat dhe fjalëkalimet. Prandaj, qëllimi im kryesor si arkitekt ishte të vendosja gjilpërën e nxehtë të kriptoanalizës sa më larg që të ishte e mundur nga elementet e infrastrukturës që më janë të shtrenjta.

Nuk janë çelësat e tu, nuk janë problemet e tua.

Ne po ndërtojmë një sistem shkëmbimi aktivesh dhe duam të përjashtojmë ruajtjen ndërmjetësore të këtyre aktiveve, por duhet të sigurojmë sigurinë e transaksionit.

Mund të veprosh si gjyqtar në një situatë spori dhe të realizosh transaksione me portofolat që kërkojnë dy nga tre nënshkrime: blerësi, shitësi dhe escrow.

Megjithatë, nëse një pjesëmarrës e sulmon me sukses escrow-in, ai merr dy nënshkrimet e dëshiruara.

Swap-i atomik është një schemë shkëmbimi, ku garant i saj është smart kontrakti, i cili lejoi vetëm sjellje të ndershme.

Ashtu si në enigmën për ujkun, kozën dhe kapustën, ti mund të veprosh vetëm sipas një skenari të vetëm të saktë dhe do të pësojë humbje nëse devijon nga ai.

Por në vend të kafshëve ndotëse, rendi sigurohet nga funksioni hash, në të cilin është kaq e vështirë të gjesh një kolizion, sa nuk ia vlen të fillosh.

Hapi i parë: enigmat.

Le të supozojmë se Alisa, një mëngjes të bukur, dëshiron të transferojë Bobit bitcoin për një grusht “kriptojuanesh”.

  • Ajo zbulon një sekret të madh.
  • Merr nga ai një hash.
  • Transferon bitcoin në smart kontrakt, nga i cili paratë mund t'i marrë Bobi, duke paraqitur sekretin (hash-i nga ai duhet të barazojë atë të specifikuar në kontratën).
  • Nëse Bobi nuk e merr bitcoin-in e tij deri në mbrëmje, Alisa mund të marrë ata përsëri për vete.

Hapi i dytë: kurthi.

Në lojë hyn Bobi dhe transferon “kriptoeuro” në kontraktin e tij, i cili është shkruar në një mënyrë që:

  • Alisa mund të marrë “kriptojenet” duke paraqitur një numër sekret.
  • Jo më herët sesa pasdite, Bobi, nëse Alisa nuk shfaqet, mund të rikthejë depozitën e tij.

Hapi i tretë: zbulimi në kurth.

Alisa vjen për paratë e saj dhe merr paratë nga kontrata e Bobit, duke zbuluar kështu sekretin e saj.

Hapi përfundimtar: enigmat është zgjidhur

Transaksionin e sheh Bobi, dhe me sy shqiponje e nxjerr atë sekret, të paraqitur nga Alisa në kontratë. Ky sekret ai e përdor për të marrë bitcoinët e tij.

Kur diçka shkon keq

Nëse Alisa papritur bëhet e vdekur, Bobi merr juanët e tij në drekë.

Nga ana tjetër, Alisa në mbrëmje kthehet me bitcoin, nëse Bobi tradhëtar vendos ta mbajë paratë për kohë më të mira.

Nëse preferoni një imazh më shumë se tekstin, në Habr për ju ka një shpjegim më të detajuar dhe vizual për funksionimin e swap-eve atomike.

Dallimi midis skadimeve është dizajnuar për të na mbrojtur nga Alisa e keqe, e cila merr paratë e Bobit në momentin më të fundit, ndërsa skadimi kalon, për sa kohë ai po merr frymë me gishta të dridhura duke futur hex në transaksion.

Pjesëmarrësit nuk mund të humbin paratë e tyre, maksimumi, do të duhet të presin kthimin.

Mbështetje në bllokadëKjo është një skemë e thjeshtë, si një këpucë, që kërkon vetëm pak nga bllokat që bashkëpunojnë:

  • Mbështetje për kontratat e mençura me të paktën një degëzim
  • Të dy bllokat duhet të mbështesin algoritme të njëjta hash-shi (mos harroni të kontrolloni gjatësi e sekretit)
  • Kohëzgjatjet.

Me një vështrim të parë, mund të thuhet tanimë “lamtumirë burse, takimi ynë ishte një gabim”, por jo kaq lehtë.

Pavarësisht të gjithë përfitimeve të saj, zgjidhjet në swap atomik nuk janë të mahnitshme në likuiditet. Shumë për shkak se në çiftin më të popullarizuar BTC-USD, pjesa fiat nuk ishte plotësisht e tokenizuar.
Suksesi i USDT ka shkaktuar një valë të tërë të monedhave stabile në formatin ERC20 sipas çdo shije, nga më mbështetësja USDC deri te më algoritmike DAI.

Prandaj, për thjeshtësi ne flasim më tutje se Alisa po shet Bobit bitcoin për disa tokena ERC20, dhe shpresojmë për fatin e stabilizatorëve, për fatin tonë kemi akoma më shumë probleme teknike.

Shpejtësia

Bitcoin dhe Ethereum veç e veç nuk janë shumë të shpejtë, dhe tani na duhet të presim fillimisht një depozitë me të gjitha miratimet, pastaj tjetrën.

Kjo është për shkak se fillimisht paratë depozitohet nga pjesëmarrësi, i cili e di sekretin, dhe rivali pret finalizimin dhe vetëm atëherë kalon pjesën e tij.

Për më tepër, ne jemi duke u marrë me një aset shumë të paqëndrueshëm, kështu që gjatë këtij kohë, çmimi mund të ndryshojë ndjeshëm, dhe ndryshimi i kushteve është tashmë i vështirë.

Privatësia

Çdo shkëmbim lë pas artefakte në të dyja blockchain-et. Një vëzhgues i kujdesshëm mund të vërejë hash të njëjta në kontratat smart dhe të nxjerrë një përfundim logjik se këtu është realizuar një transaksion, nga i cili mund të nxirren shumë përfundime nga ato financiare deri te ato tatimore.

Kur bursa di për çështjet e tua — është jashtëzakonisht e pakëndshme, kur gjithë të tjerët e dinë — është dyfish e pakëndshme.

Përdorshmëria

Një veçori thelbësore e blockchain-it, sidomos e Ethereum-it. Le të shikojmë se çfarë lëvizjesh duhet të bëjë shitësi dhe blerësi.

Nga këndvështrimi i shitësit, gjithçka është relativisht e thjeshtë: thjesht duhet të transferojë bitcoin në adresën p2sh. Me Ethereum-in, gjërat janë shumë më të komplikuara.

KontrataLe të shqyrtojmë një kontratë të mesme nga GitHub për shkëmbim:

contract iERC20 {
    function totalSupply() public view returns (uint256);
    function transfer(address receiver, uint numTokens) public returns (bool);
    function balanceOf(address tokenOwner) public view returns (uint);
    function approve(address delegate, uint numTokens) public returns (bool);
    function allowance(address owner, address delegate) public view returns (uint);
    function transferFrom(address owner, address buyer, uint numTokens) public returns (bool);
}

contract Swapper {

    struct Swap {
        iERC20 token;
        bytes32 hash;
        uint amount;
        uint refundTime;
        bytes32 secret;
    }

    mapping (address => mapping(address => Swap)) swaps;

    function create(iERC20 token, bytes32 hash, address receiver, uint amount, uint refundTime) public {
        require(swaps[msg.sender][receiver].amount == 0); // check is swap with given hash already exists
        require(token.transferFrom(msg.sender, address(this), amount)); // transfer locked tokens to swap contract
        swaps[msg.sender][receiver] = Swap(token, hash, amount, refundTime, 0x00); //create swap
    }
    
    function hashOf(bytes32 secret) public pure returns(bytes32) {
        return sha256(abi.encodePacked(secret));
    }


    function withdraw(address owner, bytes32 secret) public {
        Swap memory swap = swaps[owner][msg.sender];
        require(swap.secret == bytes32(0));
        require(swap.hash == sha256(abi.encodePacked(secret))); // swap exists
        swaps[owner][msg.sender].secret = secret;
        swap.token.transfer(msg.sender, swap.amount);
    }

    function refund(address receiver) public {
        Swap memory swap = swaps[msg.sender][receiver];
        require(now > swap.refundTime);
        delete swaps[msg.sender][receiver];
        swap.token.transfer(msg.sender, swap.amount);
    }
}

Kujdes! Mos e përdorni këtë dhe kontratat e tjera nga ky artikull në prodhim, ato janë shkruar ekskluzivisht për demonstrim. Sidomos kjo.

  • Bobi duhet të thërrasë metodën e kontratës së tokens approve, duke i dhënë kontratës së shkëmbimit akses në tokenat e tij
  • Bobi krijon një shkëmbim dhe kontratën duke përdorur metodën transferFrom dhe merr në adresën e tij tokenat e dërguesit
  • Alisa në withdraw zbulon sekretin dhe kontrata thërret transfer

Shumica e xhelave dhe kriptoburseve nuk mbështesin approve tokenët, dhe nuk është pa arsye.

Këta përdorues shpesh gabojnë dhe thjesht transferojnë tokenë në kontratën, pas së cilës tokenët humbasin. Komentet në Etherscan janë plot me ankesat e të mjerëve.

Për të thirrur kontratën, duhet të paguani një tarifë në ETH, kështu që të dy palët duhet të kenë disa para përpara fillimit të marrëveshjes, dhe këtë pak kush dëshiron ta bëjë.

Gazgërmuesi

Fillimisht duhet të hiqni verifikimin e dërguesit gjithandej ku është e mundur dhe të supozoni se kemi dikë që vuajnë nga mbiprodhim gazi dhe thërret kontrata për të gjithë që duan.

Kontrata e modernizuar

contract Swapper {

    struct Swap {
        iERC20 token;
        address receiver;
        uint amount;
        address refundAddress;
        uint refundTime;
    }

    mapping (bytes32 => Swap) swaps;

    function create(iERC20 token, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime) public {
        require(swaps[hash].amount == 0); // use hash once
        require(token.transferFrom(msg.sender, address(this), amount));
        swaps[hash] = Swap(token, receiver, amount, refundAddress, refundTime);
    }


    function withdraw(bytes memory secret) public {
        bytes32 hash = sha256(secret);
        Swap memory swap = swaps[hash];
        require(swap.amount > 0);
        delete swaps[hash];
        swap.token.transfer(swap.receiver, swap.amount);
    }

    function refund(bytes32 hash) public {
        Swap memory swap = swaps[hash];
        require(now > swap.refundTime);
        delete swaps[hash];
        swap.token.transfer(swap.refundAddress, swap.amount);
    }
}

Dualizmi kontrakt-kyç dhe EIP 712

Siç e dimë, adresa në eter mund të jetë një kontratë, ose mund të jetë një subjekt, dmth një kyç.
Aktiviteti kryesor i kyçit është të nënshkruajë disa mesazhe.

Ne mund të përdorim kontratën e Bob-it si dërgues, e cila bën të gjitha kalimet e nevojshme, pasi të ketë verifikuar nënshkrimin e Bob-it kyç.

Tani, kushdo mund të sponsorizojë tarifën e pjesëmarrësit, por vetëm ai që e di kyçin merr vendimin.

Kontrata e Bob-it

library EIP712ProxyLibrary {
    function hashCommand(address sender, iERC20 token, Swapper swapper, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime) public view returns(bytes32);
}

contract ProxyBob {
    address owner;

    constructor(address _owner) public {
        owner = _owner;
    }

    function createSwap(Swapper swapper, iERC20 token, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime, uint8 v, bytes32 r, bytes32 s) public {
        require(owner == ecrecover(EIP712ProxyLibrary.hashCommand(address(this), token, swapper, hash, receiver, amount, refundAddress, refundTime), v, r, s));
        token.approve(address(swapper), amount);
        swapper.create(token, hash, receiver, amount, refundAddress, refundTime);
    }
}

Për punën me nënshkrime të strukturave të dhënash të ndërlikuara në Ethereum ekziston një standard EIP 712, mund të lexoni më shumë rreth tij në blogun e portofolit Metamask

Ndaj dhe sundo

Shpesh skenari i hackimit të kontratës Ethereum duket kështu:

  • Pjesëmarrësi vendos fonde në kontratë
  • Pastaj tërheq fonde
  • Diçka shkon keq
  • Sulmuesi merr paratë përsëri dhe përsëri

Nëse kthehemi në shembullin tonë të parë, diçka shkon keq nëse enigmat është një grup i zbrazët bytes.

Si të vjedhësh një milionKrijojmë një swap me hash 0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
Ky është sha256 nga 0x0000000000000000000000000000000000000000000000000000000000000000
Kalojmë sekretin dhe marrim tokenet tona
Kalojmë përsëri dhe marrim të huajat, gjithë kjo sepse 0 = 0

Duke krijuar një kontratë të veçantë për çdo marrëveshje, ne mund të izolojmë kontratat në nivelin EVM.

Por kjo nuk është e gjitha: tani çdo marrëveshje ka adresën e saj, në të cilën është e mundur të dërgohen tokenet nga çdo portofol ose shkëmbim.

Kontratat e braktisura dhe create2

Por tani për çdo marrëveshje duhet të krijojmë një kontratë dhe të presim derisa blerësi të dërgojë punën e tij 'kriptomundore'. Në skemën 'në mëngjes kontratat, në mbrëmje paratë' gjithmonë ekziston rreziku që blerësi të largohet, ndërsa ethe për krijimin e kontratës janë tashmë të shpenzuara.

A mund të bëjmë që në mëngjes të jenë paratë, dhe në mbrëmje bytes?

Në hardfork-un Constantinople zhvilluesit EIP 1014 shtuan direktivën create2, e cila krijon një kontratë të re në një adresë të caktuar

keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]

Ku

  • address — adresa e kontratës fabrikë
  • salt — një numër i caktuar, kuptimi i të cilit do ta kuptojmë në serinë e ardhshme
  • init_code — kodi në byte të kontratës dhe parametrat e konstruktorit.

FabrikaDirektiva funksionon vetëm përmes assembly, kështu që fabrika duket disi e frikshme:

contract Factory {
  event Deployed(address addr, uint256 salt);

  function create2(bytes memory code, uint256 salt) public {
    address addr;
    assembly {

      addr := create2(0, add(code, 0x20), mload(code), salt)
    }

    emit Deployed(addr, salt);
  }
}

Kodi i kontratës tuaj mund të merret nëpërmjet web3:

const MyContract = new web3.eth.Contract(ABI, {})
const code = MyContract.deploy({
    data: BYTECODE,
    arguments: contructorArgs  
}).encodeABI();
const factory = new web3.eth.Contract(FACTORY_ABI, factoryAddress);
tx = factory.methods.create2(code, salt);

Për shkak të mbështetjes së kufizuar në solidity, gazi për kontratën mund të llogaritet gabim për shkak të disa nuancave të etheve.

Veçanërisht e bukur është që në rastin e mungesës së gazit, kontrata bie me një gabim të brendshëm, pa e bërë të qartë se gazit nuk ka mjaft, siç mund të pritet.

Tani, ne mund të transferojmë tokene në kontrata pa i krijuar ato më parë dhe derisa t'i publikojmë në rrjet, askush nuk do të dyshojë se çfarë bën kontrata.

Korbi nuk i nxjerr sytë korbit tjetër.

E qartë, që një analist i vërtetë, sidomos ai që ka marrë investime të mira për të luftuar armiqtë e sistemit përmes pastrimit të parave, nuk do të ndalet nga këto trillime fëmijësh, dhe pas krijimit të kontratës ai përsëri do të shohë hash-in.

Si ta bëjmë që hash-i të mos ekspozohet?

Ne transferojmë vetë swap-in në offchain: pjesëmarrësit shkëmbejnë nënshkrime për transferimin në kontratën e swap-it dhe më pas sekreti zbullohet në privat.

Hapi pas hapiKrijohen dy 'multisig' nga të cilat mund të tërhiqen fonde vetëm nëse ka nënshkrime nga Alice dhe Bob.

Për të siguruar që largimi offline i ndonjërit prej pjesëmarrësve nuk të bëjë tragjedi, do të shtojmë një ndihmë të vjetër, timeout-in.

Alice dhe Bob njëkohësisht depozitojnë.

  • Alice shpik një sekret dhe i dërgon Bob-it hash-in e sekretit dhe nënshkrimin e transaksionit që transferon bitcoin në adresën e swap-it.
  • Bob i dërgon Alice-s nënshkrimin për të tërhequr token-at në kontratën e swap-it me hash-in e shpikur.
  • Alice i tregon Bob-it sekretin.

Në këtë moment arrin harmonia: si Alice ashtu edhe Bob mund të përfundojnë marrëveshjen në çdo moment. Në një ambient kaq miqësor, ata mund të shkëmbejnë nënshkrime për tërheqjen e parave në adresat përfundimtare.

Për një vëzhgues të jashtëm, kjo duket si të gjitha paratë kaluan nëpër një kontratë me multipodpis 2 nga 2.

Përveç kësaj, një skemë e tillë lejon të dy palët të bëjnë një depozitë njëkohësisht, sepse sekreti shpiket pas të gjitha konfirmimeve.

Niveli 2

Tani që ne mund të tërheqim para në një adresë dhe të mos publikojmë transaksionin ndërmjetës, asgjë nuk na pengon të tërheqim para në disa adresa dhe të kryejmë një numër të pakufizuar transaksionesh ndërmjetës. Nuk do të thoja se është një grup i nevojshëm për shkëmbim, por nëse e ke filluar një swap, është e vështirë të ndalesh.

Tani Alice dhe Bob do të kenë mundësi të zhvillohen plotësisht. Për shembull, llogaritni automatikisht çmimin mesatar, duke shkëmbyer në satoshi për sekondë, ose thjesht lidhni drejtpërdrejt krijuesin e tregut dhe merrësin e likuiditetit.

Hapi pas hapi

  • Shitësi shpik një sekret dhe i jep blerësit hash-in e sekretit dhe nënshkrimin e transaksionit ku një pjesë e fondeve transferohet në adresën p2sh të swap-it, ndërsa pjesa tjetër kthehet në adresën e shitësit.
  • Kurshtari përcjell një nënshkrim që lejon nxjerrjen e tokens dhe kthimin në adresën e marrësit.
  • Shitësi zbulon sekretin
  • Historia përsëritet me një sekret të ri, duke shtuar për swap dhe kthim edhe nxjerrjen e asaj që është blerë më parë në adresën e blerësit dhe tashmë i paguar në adresën e shitësit.

Tani na është e mundur tregtia p2p me shpejtësi të lartë, e rëndësishme është të ndjekim kohën dhe të mbyllim marrëveshjen para se të skadojë.

Megjithatë, duke e rregulluar pak kontratën tonë, mund t'u japim kanaleve tona pamje të përjetshme, çka do ta thjeshtonte shumë krijimin e rrjetit.

Por për këtë do të flasim në serinë e ardhshme.

Burimi: habr.com

Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS 🔥 Blini hosting të besueshëm për faqe interneti me mbrojtje nga DDoS, serverë VPS VDS | ProHoster