Friday, June 27, 2025
Homeอีเธอเรียมความแข็งแกร่ง 0.6.x คุณสมบัติ: คำสั่งลอง/จับ

ความแข็งแกร่ง 0.6.x คุณสมบัติ: คำสั่งลอง/จับ



ที่ ลอง/จับไวยากรณ์แนะนำใน 0.6.0 การก้าวกระโดดที่ยิ่งใหญ่ที่สุดในการจัดการความผิดพลาดในความแข็งแกร่งเนื่องจากเหตุผลสำหรับสตริงสำหรับ ย้อนกลับ และ จำเป็นต้อง ได้รับการปล่อยตัวใน v0.4.22 ทั้งคู่ พยายาม และ จับ ได้รับการจองคำหลัก ตั้งแต่ v0.5.9 และตอนนี้เราสามารถใช้พวกเขาเพื่อจัดการกับความล้มเหลวใน ภายนอก การเรียกใช้ฟังก์ชั่นโดยไม่ย้อนกลับธุรกรรมที่สมบูรณ์ (การเปลี่ยนแปลงสถานะในฟังก์ชั่นที่เรียกว่ายังคงย้อนกลับไป แต่สิ่งที่อยู่ในฟังก์ชั่นการโทรไม่ได้)

เรากำลังก้าวไปอีกขั้นหนึ่งจากวิธีการที่ไร้เดียงสา “ทั้งหมดหรือไม่มีอะไร” ในวงจรชีวิตการทำธุรกรรมซึ่งขาดพฤติกรรมการปฏิบัติที่เราต้องการบ่อยครั้ง

การจัดการความล้มเหลวของการโทรภายนอก

คำสั่ง Attempt/Catch ช่วยให้คุณสามารถตอบสนองต่อความล้มเหลวได้ ภายนอก การโทรและ การสร้างสัญญา โทรหาคุณไม่สามารถใช้งานได้ ภายใน การเรียกใช้ฟังก์ชัน โปรดทราบว่าในการปิดการเรียกใช้ฟังก์ชันสาธารณะภายในสัญญาเดียวกันกับ Attempt/Catch มันสามารถทำได้ภายนอกได้โดยเรียกฟังก์ชั่นด้วย นี้.

ตัวอย่างด้านล่างแสดงให้เห็นว่าการลอง/จับถูกใช้ในรูปแบบโรงงานที่การสร้างสัญญาอาจล้มเหลว ต่อไปนี้ องค์กรการกุศล สัญญาต้องใช้ทรัพย์สินที่อยู่บังคับ _เจ้าของ ในตัวสร้าง

pragma solidity ^0.6.1;

contract CharitySplitter {
    handle public proprietor;
    constructor (handle _owner) public {
        require(_owner != handle(0), "no-owner-provided");
        proprietor = _owner;
    }
}

มีสัญญาจากโรงงาน – องค์กรการกุศล ซึ่งใช้ในการสร้างและจัดการอินสแตนซ์ของ องค์กรการกุศล– ในโรงงานเราสามารถห่อไฟล์ ใหม่ Charitysplitter (องค์กรการกุศล) ในการลอง/จับเป็น failsafe สำหรับเมื่อตัวสร้างนั้นอาจล้มเหลวเนื่องจากว่างเปล่า เจ้าขององค์กรการกุศล ถูกส่งผ่าน

pragma solidity ^0.6.1;
import "./CharitySplitter.sol";
contract CharitySplitterFactory {
    mapping (handle => CharitySplitter) public charitySplitters;
    uint public errorCount;
    occasion ErrorHandled(string motive);
    occasion ErrorNotHandled(bytes motive);
    perform createCharitySplitter(handle charityOwner) public {
        strive new CharitySplitter(charityOwner)
            returns (CharitySplitter newCharitySplitter)
        {
            charitySplitters(msg.sender) = newCharitySplitter;
        } catch {
            errorCount++;
        }
    }
}

โปรดทราบว่าด้วยการลอง/จับมีเพียงข้อยกเว้นที่เกิดขึ้นภายในการโทรภายนอกเอง ข้อผิดพลาดภายในนิพจน์จะไม่ถูกจับตัวอย่างเช่นหากพารามิเตอร์อินพุตสำหรับ องค์กรการกุศลใหม่ เป็นส่วนหนึ่งของการโทรภายในข้อผิดพลาดใด ๆ ที่เกิดขึ้นจะไม่ถูกจับ ตัวอย่างที่แสดงให้เห็นถึงพฤติกรรมนี้คือการแก้ไข createcharitysplitter การทำงาน. นี่คือ องค์กรการกุศล พารามิเตอร์อินพุตคอนสตรัคเตอร์จะถูกดึงออกมาจากฟังก์ชั่นอื่น – แบบไดนามิก – GetCharityOwner– หากฟังก์ชั่นนั้นเปลี่ยนกลับในตัวอย่างนี้ด้วย “rethert-required-testing”นั่นจะไม่ถูกจับในคำสั่งลอง/จับ

perform createCharitySplitter(handle _charityOwner) public {
    strive new CharitySplitter(getCharityOwner(_charityOwner, false))
        returns (CharitySplitter newCharitySplitter)
    {
        charitySplitters(msg.sender) = newCharitySplitter;
    } catch (bytes reminiscence motive) {
        ...
    }
}
perform getCharityOwner(handle _charityOwner, bool _toPass)
        inner returns (handle) {
    require(_toPass, "revert-required-for-testing");
    return _charityOwner;
}

การดึงข้อความแสดงข้อผิดพลาด

เราสามารถขยายตรรกะการลอง/จับได้เพิ่มเติมในไฟล์ createcharitysplitter ฟังก์ชั่นเพื่อดึงข้อความแสดงข้อผิดพลาดหากมีการปล่อยออกมาโดยความล้มเหลว ย้อนกลับ หรือ จำเป็นต้อง และปล่อยมันในเหตุการณ์ มีสองวิธีในการบรรลุเป้าหมายนี้:

1. ใช้ ข้อผิดพลาดจับ (เหตุผลหน่วยความจำสตริง)

perform createCharitySplitter(handle _charityOwner) public {
    strive new CharitySplitter(_charityOwner) returns (CharitySplitter newCharitySplitter)
    {
        charitySplitters(msg.sender) = newCharitySplitter;
    }
    catch Error(string reminiscence motive)
    {
        errorCount++;
        CharitySplitter newCharitySplitter = new
            CharitySplitter(msg.sender);
        charitySplitters(msg.sender) = newCharitySplitter;
        // Emitting the error in occasion
        emit ErrorHandled(motive);
    }
    catch
    {
        errorCount++;
    }
}

ซึ่งปล่อยเหตุการณ์ต่อไปนี้ในตัวสร้างที่ล้มเหลวต้องมีข้อผิดพลาด:

CharitySplitterFactory.ErrorHandled(
    motive: 'no-owner-provided' (sort: string)
)

2. ใช้ จับ (เหตุผลหน่วยความจำไบต์)

perform createCharitySplitter(handle charityOwner) public {
    strive new CharitySplitter(charityOwner)
        returns (CharitySplitter newCharitySplitter)
    {
        charitySplitters(msg.sender) = newCharitySplitter;
    }
    catch (bytes reminiscence motive) {
        errorCount++;
        emit ErrorNotHandled(motive);
    }
}

ซึ่งปล่อยเหตุการณ์ต่อไปนี้ในตัวสร้างที่ล้มเหลวต้องมีข้อผิดพลาด:

CharitySplitterFactory.ErrorNotHandled(
  motive: hex'08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000116e6f2d6f776e65722d70726f7669646564000000000000000000000000000000' (sort: bytes)

สองวิธีข้างต้นสำหรับการดึงสตริงข้อผิดพลาดสร้างผลลัพธ์ที่คล้ายกัน ความแตกต่างคือวิธีที่สองไม่ได้บันทึกสตริงข้อผิดพลาด ข้อได้เปรียบของวิธีที่สองคือมันจะดำเนินการหาก ABI ถอดรหัสสตริงข้อผิดพลาดล้มเหลวหรือหากไม่มีเหตุผล

แผนการในอนาคต

มีแผนที่จะปล่อยการสนับสนุนประเภทข้อผิดพลาดซึ่งหมายความว่าเราจะสามารถประกาศข้อผิดพลาดในลักษณะเดียวกันกับเหตุการณ์ที่ช่วยให้เราสามารถจับข้อผิดพลาดประเภทต่าง ๆ ได้เช่น:

catch CustomErrorA(uint data1) {}
catch CustomErrorB(uint() reminiscence data2) {}
catch {}
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

ความเห็นล่าสุด