# Whitelisted Redemption

### Whitelisted Package Redemption

`WhitelistPackageRedemption` provides a simple example of how users can create and redeem packages using the PostOffice contract while enforcing a whitelist requirement for package redemption.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import "./PostOffice.sol";

contract WhitelistPackageRedemption {
    PostOffice public postOffice;
    mapping(address => bool) public whitelist;

    constructor(address _postOfficeAddress) {
        postOffice = PostOffice(_postOfficeAddress);
        // Add addresses to the whitelist
        whitelist[address(0x123)] = true;
        whitelist[address(0x456)] = true;
        whitelist[address(0x789)] = true;
        whitelist[address(0xABC)] = true;
        whitelist[address(0xDEF)] = true;
    }

    function shipPackage(
        CapsuleData.CapsuleContent calldata packageContent_,
        PostOffice.SecurityInfo calldata securityInfo_,
        address receiver_
    ) external returns (uint256) {
        return postOffice.shipPackage(packageContent_, securityInfo_, receiver_);
    }

    function pickupPackage(
        uint256 packageId_,
        bytes32 messageHash,
        bytes[] calldata signature_,
        string calldata rawPassword_,
        string calldata salt_,
        bool shouldRedeem_
    ) external {
        uint256 _len = signature_.length;
        require(_len == 5, "Invalid number of signatures");

        // Verify signatures from whitelisted addresses
        for (uint256 i = 0; i < _len; i++) {
            address _signer = verifySignature(messageHash, signature_[i]);
            require(whitelist[_signer], "Invalid signer");
        }
        postOffice.pickup(packageId_, rawPassword_, salt_, shouldRedeem_);
    }

    function verifySignature(bytes32 messageHash_, bytes memory signature_) internal pure returns (address) {
        bytes32 r;
        bytes32 s;
        uint8 v;

        // Split the signature into r, s, and v components
        assembly {
            r := mload(add(signature_, 32))
            s := mload(add(signature_, 64))
            v := byte(0, mload(add(signature_, 96)))
        }
        // Verify and recover the signer's address
        return ecrecover(messageHash_, v, r, s);
    }
}
```

In this contract, users can create packages by calling the `createPackage` function, providing the necessary parameters such as the package manager, receiver, password hash, and asset key. The function will invoke the `shipPackage` method from the PostOffice contract to create the package.

To redeem a package, users need to call the `redeemPackage` function with the package ID, message hash, and an array of signatures. The function will verify the signatures from the whitelisted addresses by calling the `verifySignature` function, and if all signatures are valid, it will invoke the `redeemPackage` method from the PostOffice contract.
